module Rattletrap.Type.PropertyValue where import qualified Data.Foldable as Foldable import qualified Rattletrap.ByteGet as ByteGet import qualified Rattletrap.BytePut as BytePut import qualified Rattletrap.Exception.UnknownProperty as UnknownProperty import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.Property.Array as Property.Array import qualified Rattletrap.Type.Property.Bool as Property.Bool import qualified Rattletrap.Type.Property.Byte as Property.Byte import qualified Rattletrap.Type.Property.Float as Property.Float import qualified Rattletrap.Type.Property.Int as Property.Int import qualified Rattletrap.Type.Property.Name as Property.Name import qualified Rattletrap.Type.Property.QWord as Property.QWord import qualified Rattletrap.Type.Property.Str as Property.Str import qualified Rattletrap.Type.Str as Str import qualified Rattletrap.Utility.Json as Json data PropertyValue a = -- | Yes, a list of dictionaries. No, it doesn't make sense. These usually -- only have one element. Array (Property.Array.Array a) | Bool Property.Bool.Bool | -- | This is a strange name for essentially a key-value pair. Byte Property.Byte.Byte | Float Property.Float.Float | Int Property.Int.Int | -- | It's unclear how exactly this is different than a 'StrProperty'. Name Property.Name.Name | QWord Property.QWord.QWord | Str Property.Str.Str deriving (Eq, Show) instance (Json.FromJSON a) => Json.FromJSON (PropertyValue a) where parseJSON = Json.withObject "PropertyValue" $ \object -> Foldable.asum [ fmap Array $ Json.required object "array", fmap Bool $ Json.required object "bool", fmap Byte $ Json.required object "byte", fmap Float $ Json.required object "float", fmap Int $ Json.required object "int", fmap Name $ Json.required object "name", fmap QWord $ Json.required object "q_word", fmap Str $ Json.required object "str" ] instance (Json.ToJSON a) => Json.ToJSON (PropertyValue a) where toJSON x = case x of Array y -> Json.object [Json.pair "array" y] Bool y -> Json.object [Json.pair "bool" y] Byte y -> Json.object [Json.pair "byte" y] Float y -> Json.object [Json.pair "float" y] Int y -> Json.object [Json.pair "int" y] Name y -> Json.object [Json.pair "name" y] QWord y -> Json.object [Json.pair "q_word" y] Str y -> Json.object [Json.pair "str" y] schema :: Schema.Schema -> Schema.Schema schema s = Schema.named "property-value" . Schema.oneOf $ fmap (\(k, v) -> Schema.object [(Json.pair k v, True)]) [ ("array", Schema.ref $ Property.Array.schema s), ("bool", Schema.ref Property.Bool.schema), ("byte", Schema.ref Property.Byte.schema), ("float", Schema.ref Property.Float.schema), ("int", Schema.ref Property.Int.schema), ("name", Schema.ref Property.Name.schema), ("q_word", Schema.ref Property.QWord.schema), ("str", Schema.ref Property.Str.schema) ] bytePut :: (a -> BytePut.BytePut) -> PropertyValue a -> BytePut.BytePut bytePut putProperty value = case value of Array x -> Property.Array.bytePut putProperty x Bool x -> Property.Bool.bytePut x Byte x -> Property.Byte.bytePut x Float x -> Property.Float.bytePut x Int x -> Property.Int.bytePut x Name x -> Property.Name.bytePut x QWord x -> Property.QWord.bytePut x Str x -> Property.Str.bytePut x byteGet :: ByteGet.ByteGet a -> Str.Str -> ByteGet.ByteGet (PropertyValue a) byteGet getProperty kind = ByteGet.label "PropertyValue" $ case Str.toString kind of "ArrayProperty" -> fmap Array $ Property.Array.byteGet getProperty "BoolProperty" -> fmap Bool Property.Bool.byteGet "ByteProperty" -> fmap Byte Property.Byte.byteGet "FloatProperty" -> fmap Float Property.Float.byteGet "IntProperty" -> fmap Int Property.Int.byteGet "NameProperty" -> fmap Name Property.Name.byteGet "QWordProperty" -> fmap QWord Property.QWord.byteGet "StrProperty" -> fmap Str Property.Str.byteGet x -> ByteGet.throw $ UnknownProperty.UnknownProperty x