hosc-0.16: Sound/OSC/Datum/Datem.hs
-- | A class for translating to and from 'Datum'.
module Sound.OSC.Datum.Datem where
import qualified Data.ByteString.Lazy as Lazy {- bytestring -}
import qualified Data.ByteString.Char8 as Char8 {- bytestring -}
import Data.Int {- base -}
import Data.Maybe {- base -}
import Data.Word {- base -}
import Sound.OSC.Datum {- hosc -}
import Sound.OSC.Time {- hosc -}
{- | Class for translating to and from 'Datum'.
There are instances for the direct 'Datum' field types.
> d_put (1::Int32) == Int32 1
> d_put (1::Int64) == Int64 1
> d_put (1::Float) == Float 1
> d_put (1::Double) == Double 1
> d_put (Char8.pack "str") == ASCII_String (Char8.pack "str")
> d_put (Lazy.pack [37,37]) == Blob (blob_pack [37,37])
> d_put (MIDI 0 0 0 0) == Midi (MIDI 0 0 0 0)
There are also instances for standard Haskell types.
> d_put (1::Int) == Int64 1
> d_put (1::Integer) == Int64 1
-}
class Datem a where
d_put :: a -> Datum -- ^ Function to wrap value in 'Datum'.
d_get :: Datum -> Maybe a -- ^ Function to extract value from 'Datum'.
instance Datem Int32 where
d_put = Int32
d_get d = case d of {Int32 x -> Just x;_ -> Nothing}
instance Datem Int64 where
d_put = Int64
d_get d = case d of {Int64 x -> Just x;_ -> Nothing}
instance Datem Int where
d_put = Int64 . fromIntegral
d_get = datum_integral
instance Datem Integer where
d_put = Int64 . fromIntegral
d_get = datum_integral
instance Datem Float where
d_put = Float
d_get d = case d of {Float x -> Just x;_ -> Nothing}
instance Datem Double where
d_put = Double
d_get d = case d of {Double x -> Just x;_ -> Nothing}
instance Datem Char8.ByteString where
d_put = ASCII_String
d_get d = case d of {ASCII_String x -> Just x;_ -> Nothing}
instance Datem Lazy.ByteString where
d_put = Blob
d_get d = case d of {Blob x -> Just x;_ -> Nothing}
instance Datem MIDI where
d_put = Midi
d_get d = case d of {Midi x -> Just x;_ -> Nothing}
-- | Error variant of 'd_get'.
d_get_err :: Datem a => Datum -> a
d_get_err = fromMaybe (error "d_get") . d_get
-- * Type specialised
-- | Type specialised 'd_get'.
--
-- > map datum_int32 [Int32 1,Float 1] == [Just 1,Nothing]
datum_int32 :: Datum -> Maybe Int32
datum_int32 = d_get
-- | Type specialised 'd_get'.
datum_int64 :: Datum -> Maybe Int64
datum_int64 = d_get
-- | Type specialised 'd_get'.
datum_float :: Datum -> Maybe Float
datum_float = d_get
-- | Type specialised 'd_get'.
datum_double :: Datum -> Maybe Double
datum_double = d_get
-- | Type specialised 'd_get'.
--
-- > datum_ascii (d_put (Char8.pack "string")) == Just (Char8.pack "string")
datum_ascii :: Datum -> Maybe ASCII
datum_ascii = d_get
-- | 'Char8.unpack' of 'd_get'.
--
-- > datum_string (d_put (Char8.pack "string")) == Just "string"
-- > map datum_string [string "string",Int32 5] == [Just "string",Nothing]
datum_string :: Datum -> Maybe String
datum_string = fmap Char8.unpack . datum_ascii
-- | Type specialised 'd_get'.
datum_blob :: Datum -> Maybe Lazy.ByteString
datum_blob = d_get
-- | 'Maybe' variant of 'd_timestamp'.
datum_timestamp :: Datum -> Maybe Time
datum_timestamp d = case d of {TimeStamp x -> Just x;_ -> Nothing}
-- | Type specialised 'd_get'.
datum_midi :: Datum -> Maybe MIDI
datum_midi = d_get
-- | 'Datum' as sequence of 'Word8' if 'ASCII_String', 'Blob' or 'Midi'.
--
-- > let d = [string "5",Blob (Lazy.pack [53]),midi (0x00,0x90,0x40,0x60)]
-- > in Data.Maybe.mapMaybe datum_sequence d == [[53],[53],[0,144,64,96]]
datum_sequence :: Datum -> Maybe [Word8]
datum_sequence d =
case d of
ASCII_String s -> Just (map (fromIntegral . fromEnum) (Char8.unpack s))
Blob s -> Just (Lazy.unpack s)
Midi (MIDI p q r s) -> Just [p,q,r,s]
_ -> Nothing