#ifndef SIMPLESTRUCT_S11N_H_INCLUDED
#define SIMPLESTRUCT_S11N_H_INCLUDED 1

#include "simplestruct.h"

//////////////////////////////////////////////////////////////////////
// Our s11n proxy, to save simplestructs:
//////////////////////////////////////////////////////////////////////
struct simplestruct_s11n
{
        /**
        Serialize src to dest.

        DataNodeType is an abstract concept. See s11n::data_node
        for the implementation used here.
        */
        template <typename DataNodeType>
        bool operator()( DataNodeType & dest, const simplestruct & src ) const
        {
                // note: because simplestruct is monomorphic, we do not
                // need to set dest.impl_class(). The core can reliably
                // set this for MONOMORPHIC types, so it does.
                dest.set( "int", src.i );
                dest.set( "dbl", src.d );
                dest.set( "str", src.s );
                return  (!src.child)
                        ? true // we don't care if it has a child or not.
                        : s11nlite::serialize( s11n::create_child( dest, "child" ), src.child );
                ////////////////////////////////////////////////////////////
                // Just for example, below shows full error-checking case
                // for the child, which would be the proper thing to
                // do in most cases. It avoids adding a child to dest
                // if the child fails to serialize.
                // Oddly enough, the single-child case is
                // more work than a container of children!
                // Since we "know" that this type can't really fail to
                // serialize (because this type controls that), the
                // error checking would be largely redundant here.
                /************************************************************
                if( src.child )
                {
                        DataNodeType * ch = new DataNodeType;
                        if( ! s11nlite::serialize( *ch, src.child ) )
                        {
                                // child failed to serialize :(
                                delete( ch );
                                return false;
                        }
                        ch->name( "child" );
                        dest.children().push_back( ch );
                }
                ************************************************************/
        }

        /**
        Deserialize dest from src.

        DataNodeType is an abstract concept. See s11n::data_node
        for the implementation used here.
        */
        template <typename DataNodeType>
        bool operator()( const DataNodeType & src, simplestruct & dest ) const
        {
                delete( dest.child );
                dest.i = src.get( "int", -1 );
                dest.d = src.get( "dbl", -1.0 );
                dest.s = src.get( "str", "NOT SET" );
                // Again: a single-child case is normally more work
                // than a container of children!
                // In the case of deserialization we generally must
                // check and see if the child node is there before
                // continuing, so there is not much way around this
                // except to write a convenience function:
                if( const DataNodeType * ch = s11n::find_child_by_name( src, "child" ) )
                {
                        dest.child = new simplestruct;
                        if( ! s11nlite::deserialize( *ch, dest.child ) )
                        {
                                // deser'd child is now in an undefined
                                // state, so we get rid of it:
                                delete( dest.child );
                                dest.child = 0;
                                return false;
                        }
                }
                return true;
        }
};

////////////////////////////////////////////////////////////////////////
// s11n registration:
////////////////////////////////////////////////////////////////////////
#include <s11n.net/s11n/s11nlite.hpp> // s11n/s11nlite framework
//////////////////////////////////////////////////////////////////////
// Register the proxy with s11n. We match the TYPE we'd like to
// proxy with the TYPE of the proxy, and supply a class name
// for the proxIED type with it's classloader:
#define S11N_TYPE simplestruct                    // TYPE to proxy
#define S11N_NAME "simplestruct"                  // type NAME
#define S11N_SERIALIZE_FUNCTOR simplestruct_s11n // PROXY type
#include <s11n.net/s11n/reg_proxy.hpp>                    // registration code
//////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////
// Done! Now use simplestruct like any Serializable type,
// using s11n's *easy* API!
//////////////////////////////////////////////////////////////////////

#endif // SIMPLESTRUCT_S11N_H_INCLUDED

