From f0f5fa44dd3dbc2a5a6308e2dce047a82c8b1be2 Mon Sep 17 00:00:00 2001 From: stuebinm Date: Wed, 23 Nov 2022 23:39:27 +0100 Subject: VDV 452 instances for serialisation this may occasionally produce wrong output. In a lot of places I'm not entirey sure if I understood the standard correctly … --- vdv-server/VDV451.hs | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'vdv-server/VDV451.hs') diff --git a/vdv-server/VDV451.hs b/vdv-server/VDV451.hs index 1d56e1c..b962208 100644 --- a/vdv-server/VDV451.hs +++ b/vdv-server/VDV451.hs @@ -47,10 +47,6 @@ instance ÖPNVEncode Text where instance ÖPNVEncode Day where encode day = "\""+|crop 2 d|+"."+|crop 2 m|+"."+|crop 4 y|+"\"" where (y,m,d) = toGregorian day - crop n thing = if T.length shown < n - then T.replicate (n - T.length shown) "0" <> shown - else T.takeEnd n shown - where shown = T.pack $ show thing -- | for things which can be encoded as either string or number, -- this module defaults to strings. Add this newtype to the schema @@ -69,6 +65,32 @@ instance ÖPNVEncode Int instance ÖPNVEncode Integer +-- | these are encoded in a horrible format +newtype Longitude = Longitude Double +newtype Latitude = Latitude Double + +encodeGeoLength :: Double -> ByteString +encodeGeoLength d' = ""+|sign|+""+|crop 3 deg|+""+|crop 2 min|+""+|crop 5 sec|+"" + where deg = truncate d + min = truncate (d * 60) `mod` 60 + sec = truncate (d * 3600 * 1000) `mod` (60 * 1000) + d = abs d' + sign :: Text + sign = if d' < 0 then "-" else "" + +instance ÖPNVEncode Latitude where + encode (Latitude d) = encodeGeoLength d +instance ÖPNVEncode Longitude where + encode (Longitude d) = encodeGeoLength d + +-- | this isn't specified anywhere, but seems to be what VDV 452 implies +instance ÖPNVEncode a => ÖPNVEncode (Maybe a) where + encode (Just a) = encode a + encode Nothing = "NULL" + +instance ÖPNVEncode Bool where + encode False = "0" + encode True = "1" data ÖPNVBefehl = MOD | SRC | CHS | VER | IFV @@ -102,6 +124,7 @@ instance ÖPNVEncode ÖPNVType where class ÖPNVDatum a where tableName :: Proxy a -> ByteString + tableNumber :: Proxy a -> Int tableSchema :: Proxy a -> [(ByteString, ÖPNVType, a -> Feld)] encodeRow :: forall a. ÖPNVDatum a => a -> [Feld] @@ -145,3 +168,9 @@ data ÖPNVOptions = ÖPNVOptions . C8.intercalate "; " . fmap (\case { (F a) -> encode a; Raw a -> a }) (colNames, colTypes) = unzip (tableInfo (Proxy @a)) + + +crop n thing = if T.length shown < n + then T.replicate (n - T.length shown) "0" <> shown + else T.takeEnd n shown + where shown = T.pack $ show thing -- cgit v1.2.3