@ -1,17 +1,31 @@
//! The available formats to convert
//! The available formats to convert
use super ::* ;
use super ::* ;
use std ::io ;
use std ::io ;
use std ::{
error , fmt ,
} ;
use object ::Object ;
use object ::Object ;
/// `Format` impl for JSON.
mod json ;
/// Config for the encode/decode
/// Config for the encode/decode
pub struct Config ;
pub struct Config ; //TODO: What goes here?
/// A directive for a format on how to encode and decode objects.
/// A directive for a format on how to encode and decode objects.
#[ derive(Clone, Copy) ]
#[ derive(Clone, Copy) ]
pub struct FormatDirective
pub struct FormatDirective
{
{
encode : fn ( & Config , & mut dyn io ::Write , & Object ) -> io ::Result < usize > ,
encode : fn ( & Config , & mut dyn io ::Write , & Object ) -> Result < usize , Error > ,
decode : fn ( & Config , & mut dyn io ::Read ) -> io ::Result < ( Object , usize ) > ,
decode : fn ( & Config , & mut dyn io ::Read ) -> Result < ( Object , usize ) , Error > ,
}
/// Trait for statically implementing formatters to/from `Object`.
pub trait Format
{
fn encode < W : io ::Write > ( cfg : & Config , to : W , obj : & Object ) -> Result < usize , Error > ;
fn decode < R : io ::Read > ( cfg : & Config , from : R ) -> Result < Object , Error > ; //TODO: An `io::Read` wrapper that counter num of bytes read internally. That way we can extract `(Object, usize)` from just `Object` here.
}
}
macro_rules! directive {
macro_rules! directive {
@ -21,11 +35,117 @@ macro_rules! directive {
decode : $decode ,
decode : $decode ,
} )
} )
} ;
} ;
( for $fmt :path = > $( $name :literal ) , + ) = > {
//TODO: $fmt will be a struct implementing `Format`.
// Will perform input conversions to trait methods.
// Will perform input/output conversions for `Format::decode` to extract `(Object, usize)` from `Object` function output and a `io::Read` input wrapper that counts bytes read from the stream.
directive ! ( $( $name ) , + = > | c , w , o | {
< $fmt as Format > ::encode ( c , w , o )
} , | c , r | {
todo! ( "We need a io::Read stream wrapper that counts the bytes read `r` to satisfy the return value requirements of this function pointer" )
} )
}
}
}
/// All format directives and their name(s)
/// All format directives and their name(s)
pub static FORMATS : & [ ( & ' static [ & ' static str ] , FormatDirective ) ] = & [
pub static FORMATS : & [ ( & ' static [ & ' static str ] , FormatDirective ) ] = & [
directive ! ( "json" , "js" , "javascript" = > | _ , _ , _ | todo! ( ) , | _ , _ | todo! ( ) ) ,
directive ! ( for json ::JsonFormatter = > "json" , "js" , "javascript" ) ,
directive ! ( "s-expression" , "sexpr" , "lisp" , "lexpr" = > | _ , _ , _ | todo! ( ) , | _ , _ | todo! ( ) ) ,
directive ! ( "s-expression" , "sexpr" , "lisp" , "lexpr" = > | _ , _ , _ | todo! ( ) , | _ , _ | todo! ( ) ) ,
directive ! ( "cbor" = > | _ , _ , _ | todo! ( ) , | _ , _ | todo! ( ) ) ,
directive ! ( "cbor" = > | _ , _ , _ | todo! ( ) , | _ , _ | todo! ( ) ) ,
] ;
] ;
/// A formatting error kind. See `Error`.
#[ derive(Debug) ]
pub enum ErrorKind
{
IO ( io ::Error ) ,
Unknown ,
}
impl From < io ::Error > for ErrorKind
{
fn from ( from : io ::Error ) -> Self
{
Self ::IO ( from )
}
}
/// A formatting error.
#[ derive(Debug) ]
pub struct Error ( ErrorKind , bool ) ;
impl Error
{
/// An encode error
#[ inline ] pub fn encode ( kind : impl Into < ErrorKind > ) -> Self
{
Self ( kind . into ( ) , true )
}
/// A decode error
#[ inline ] pub fn decode ( kind : impl Into < ErrorKind > ) -> Self
{
Self ( kind . into ( ) , false )
}
/// What kind of error was it?
#[ inline ] pub fn kind ( & self ) -> & ErrorKind
{
& self . 0
}
/// Is an encode error?
#[ inline ] pub fn is_encode ( & self ) -> bool
{
self . 1
}
/// Is a decode error?
#[ inline ] pub fn is_decode ( & self ) -> bool
{
! self . 1
}
}
impl error ::Error for Error
{
fn source ( & self ) -> Option < & ( dyn error ::Error + ' static ) > {
Some ( match & self . 0 {
ErrorKind ::IO ( i ) = > i ,
_ = > return None ,
} )
}
}
impl fmt ::Display for Error
{
fn fmt ( & self , f : & mut fmt ::Formatter < ' _ > ) -> fmt ::Result
{
write! ( f , "formatting error: " ) ? ;
if self . 1 {
write! ( f , "encode" )
} else {
write! ( f , "decode" )
}
}
}
impl From < ( io ::Error , bool ) > for Error
{
#[ inline ] fn from ( from : ( io ::Error , bool ) ) -> Self
{
Self ( ErrorKind ::IO ( from . 0 ) , from . 1 )
}
}
impl From < Error > for io ::Error
{
fn from ( from : Error ) -> Self
{
match from . 0
{
ErrorKind ::IO ( io ) = > io ,
_ = > io ::Error ::new ( io ::ErrorKind ::Other , from ) ,
}
}
}