{-# LANGUAGE GADTs #-}{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}{-# OPTIONS_GHC -fno-warn-name-shadowing #-}---- (c) The University of Glasgow 2002-2006---- Serialized valuesmoduleGHC.Serialized(-- * Main Serialized data typeSerialized (..),-- * Going into and out of 'Serialized'toSerialized ,fromSerialized ,-- * Handy serialization functionsserializeWithData ,deserializeWithData ,)whereimportPrelude-- See note [Why do we import Prelude here?]importData.BitsimportData.Word(Word8)importData.Data-- | Represents a serialized value of a particular type. Attempts can be made to deserialize it at certain typesdataSerialized =Serialized TypeRep[Word8]-- | Put a Typeable value that we are able to actually turn into bytes into a 'Serialized' value ready for deserialization latertoSerialized::foralla .Typeablea =>(a ->[Word8])->a ->Serialized toSerialized serialize what =Serialized (typeOfwhat )(serialize what )-- | If the 'Serialized' value contains something of the given type, then use the specified deserializer to return @Just@ that.-- Otherwise return @Nothing@.fromSerialized::foralla .Typeablea =>([Word8]->a )->Serialized ->Maybea fromSerialized deserialize (Serialized the_type bytes )|the_type ==rep =Just(deserialize bytes )|otherwise=Nothingwhererep =typeRep(Proxy::Proxya )-- | Use a 'Data' instance to implement a serialization scheme dual to that of 'deserializeWithData'serializeWithData::Dataa =>a ->[Word8]serializeWithData what =serializeWithData' what []serializeWithData'::Dataa =>a ->[Word8]->[Word8]serializeWithData' what =fst$gfoldl(\(before ,a_to_b )a ->(before .serializeWithData' a ,a_to_b a ))(\x ->(serializeConstr (constrRep(toConstrwhat )),x ))what -- | Use a 'Data' instance to implement a deserialization scheme dual to that of 'serializeWithData'deserializeWithData::Dataa =>[Word8]->a deserializeWithData =snd.deserializeWithData' deserializeWithData'::foralla .Dataa =>[Word8]->([Word8],a )deserializeWithData' bytes =deserializeConstr bytes $\constr_rep bytes ->gunfold(\(bytes ,b_to_r )->let(bytes' ,b )=deserializeWithData' bytes in(bytes' ,b_to_r b ))(\x ->(bytes ,x ))(repConstr(dataTypeOf(undefined::a ))constr_rep )serializeConstr::ConstrRep->[Word8]->[Word8]serializeConstr (AlgConstrix )=serializeWord8 1.serializeInt ix serializeConstr(IntConstri )=serializeWord8 2.serializeInteger i serializeConstr(FloatConstrr )=serializeWord8 3.serializeRational r serializeConstr(CharConstrc )=serializeWord8 4.serializeChar c deserializeConstr::[Word8]->(ConstrRep->[Word8]->a )->a deserializeConstr bytes k =deserializeWord8 bytes $\constr_ix bytes ->caseconstr_ix of1->deserializeInt bytes $\ix ->k (AlgConstrix )2->deserializeInteger bytes $\i ->k (IntConstri )3->deserializeRational bytes $\r ->k (FloatConstrr )4->deserializeChar bytes $\c ->k (CharConstrc )x ->error$"deserializeConstr: unrecognised serialized constructor type "++showx ++" in context "++showbytes serializeFixedWidthNum::foralla .(Integrala ,FiniteBitsa )=>a ->[Word8]->[Word8]serializeFixedWidthNum what =go (finiteBitSizewhat )what wherego::Int->a ->[Word8]->[Word8]go size current rest |size <=0=rest |otherwise=fromIntegral(current .&.255):go (size -8)(current `shiftR`8)rest deserializeFixedWidthNum::foralla b .(Integrala ,FiniteBitsa )=>[Word8]->(a ->[Word8]->b )->b deserializeFixedWidthNum bytes k =go (finiteBitSize(undefined::a ))bytes k wherego::Int->[Word8]->(a ->[Word8]->b )->b go size bytes k |size <=0=k 0bytes |otherwise=casebytes of(byte :bytes )->go (size -8)bytes (\x ->k ((x `shiftL`8).|.fromIntegralbyte ))[]->error"deserializeFixedWidthNum: unexpected end of stream"serializeEnum::(Enuma )=>a ->[Word8]->[Word8]serializeEnum =serializeInt .fromEnumdeserializeEnum::Enuma =>[Word8]->(a ->[Word8]->b )->b deserializeEnum bytes k =deserializeInt bytes (k .toEnum)serializeWord8::Word8->[Word8]->[Word8]serializeWord8 x =(x :)deserializeWord8::[Word8]->(Word8->[Word8]->a )->a deserializeWord8 (byte :bytes )k =k byte bytes deserializeWord8[]_=error"deserializeWord8: unexpected end of stream"serializeInt::Int->[Word8]->[Word8]serializeInt =serializeFixedWidthNum deserializeInt::[Word8]->(Int->[Word8]->a )->a deserializeInt =deserializeFixedWidthNum serializeRational::(Reala )=>a ->[Word8]->[Word8]serializeRational =serializeString .show.toRationaldeserializeRational::(Fractionala )=>[Word8]->(a ->[Word8]->b )->b deserializeRational bytes k =deserializeString bytes (k .fromRational.read)serializeInteger::Integer->[Word8]->[Word8]serializeInteger =serializeString .showdeserializeInteger::[Word8]->(Integer->[Word8]->a )->a deserializeInteger bytes k =deserializeString bytes (k .read)serializeChar::Char->[Word8]->[Word8]serializeChar =serializeString .showdeserializeChar::[Word8]->(Char->[Word8]->a )->a deserializeChar bytes k =deserializeString bytes (k .read)serializeString::String->[Word8]->[Word8]serializeString =serializeList serializeEnum deserializeString::[Word8]->(String->[Word8]->a )->a deserializeString =deserializeList deserializeEnum serializeList::(a ->[Word8]->[Word8])->[a ]->[Word8]->[Word8]serializeList serialize_element xs =serializeInt (lengthxs ).foldr(.)id(mapserialize_element xs )deserializeList::foralla b .(forallc .[Word8]->(a ->[Word8]->c )->c )->[Word8]->([a ]->[Word8]->b )->b deserializeList deserialize_element bytes k =deserializeInt bytes $\len bytes ->go len bytes k wherego::Int->[Word8]->([a ]->[Word8]->b )->b go len bytes k |len <=0=k []bytes |otherwise=deserialize_element bytes (\elt bytes ->go (len -1)bytes (k .(elt :)))