#pragma once #include #include #include #include #include #include #include "NetMessengerStreamBuffer.h" namespace Aftr { //See SensorDatum.h and SensorDatum.cpp for a simple "howto" usage example. This Concept class //specifies the concepts and helpful functions to make the SensorDatum derivatives easy-to-use. struct ParseError; //lightweight error returned when parsing fails, it contains an int and a string. //The most useful type is probably the string, the int may not always be used but //it is there (defaults to -1). //Easy utility function that report a human readable error message. std::optional< Aftr::ParseError > validateInputStream( std::istream& is, std::string const& location );// { return is.rdstate() == 0; } std::optional< Aftr::ParseError > validateInputStream( Aftr::NetMessengerStreamBuffer const& is, std::string const& location ); // { return is.rdstate() == 0; } std::ostream& operator<<( std::ostream& os, Aftr::ParseError const& err ); //Defines a concept for any type that, at compile time, fulfils the interface of a //SensorDatum. This could be done w/ inheritance, but dispatching on a virtual interface //when parsing millions of these datums isn't necessary, especially when every use case of //these SensorDatum types are specialized and the exact type is a template parameter known //at compile time. //A user ought to copy / paste the SensorDatum from below, change its name to SensorDatum_SuperSpecialSensor //and adjust the body of all member functions accordingly. template< typename T > concept SensorDatumConcept = requires(T t, T const& tconst, //t and tconst are the same type, just one is const std::istream& is, NetMessengerStreamBuffer& isn, std::ostream& os, std::chrono::microseconds offset) { { T::fromStreamOneDatum( is ) } -> std::convertible_to< std::expected >; //static member function { T::fromStreamOneDatum( isn ) } -> std::convertible_to< std::expected >; //static member function //To stream should terminate each datum with a \n newline { tconst.toStreamOneDatum( os ) } -> std::convertible_to< bool >; //member function must be const! { T::getHeaderDescribingData() } -> std::convertible_to< std::string >; //static member function { tconst.getTime() } -> std::convertible_to< std::chrono::utc_clock::time_point >; //const member func }; struct ParseError { int code = -1; std::string str; friend std::ostream& operator<< ( std::ostream&, ParseError const& ); }; } //namespace Aftr