avro 0.3.6.0 → 0.3.6.1
raw patch · 4 files changed
+143/−19 lines, 4 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ Data.Avro.Schema: extractBindings :: Type -> HashMap TypeName Type
Files
- avro.cabal +3/−2
- src/Data/Avro/Schema.hs +11/−16
- test/Avro/SchemaSpec.hs +24/−1
- test/data/internal-bindings.avsc +105/−0
avro.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 227dce7b3b510a3f986c3dd8ba7a73b2e32ef06ef0d81005408e20f9c8eadc2d+-- hash: 686c91bf89cf070fdd57de52066edac6394a61472b3927e5c8fab77a5c009ba1 name: avro-version: 0.3.6.0+version: 0.3.6.1 synopsis: Avro serialization support for Haskell description: Avro serialization and deserialization support for Haskell category: Data@@ -23,6 +23,7 @@ test/data/deconflict/writer.avsc test/data/enums-object.json test/data/enums.avsc+ test/data/internal-bindings.avsc test/data/karma.avsc test/data/logical.avsc test/data/maybe.avsc
src/Data/Avro/Schema.hs view
@@ -27,6 +27,7 @@ -- * Lower level utilities , typeName , buildTypeEnvironment+ , extractBindings , Result(..) , resultToEither @@ -709,22 +710,16 @@ -- Types declared implicitly in record field definitions are also included. No distinction -- is made between aliases and normal names. extractBindings :: Type -> HashMap.HashMap TypeName Type-extractBindings = typeBindings HashMap.empty- where- insertAll :: (Eq k, Hashable k) => [k] -> v -> HashMap.HashMap k v -> HashMap.HashMap k v- insertAll keys value table = foldl (\hashmap key -> HashMap.insert key value hashmap) table keys-- fieldBindings :: HashMap.HashMap TypeName Type -> Field -> HashMap.HashMap TypeName Type- fieldBindings table Field{..} = typeBindings table fldType-- typeBindings :: HashMap.HashMap TypeName Type -> Type -> HashMap.HashMap TypeName Type- typeBindings table t@Record{..} =- let withRecord = insertAll (name : aliases) t table- in HashMap.unions $ map (fieldBindings withRecord) fields- typeBindings table e@Enum{..} = insertAll (name : aliases) e table- typeBindings table Union{..} = HashMap.unions $ NE.toList $ NE.map (typeBindings table) options- typeBindings table f@Fixed{..} = insertAll (name : aliases) f table- typeBindings table _ = table+extractBindings = \case+ t@Record{..} ->+ let withRecord = HashMap.fromList $ (name : aliases) `zip` repeat t+ in HashMap.unions $ withRecord : (extractBindings . fldType <$> fields)+ e@Enum{..} -> HashMap.fromList $ (name : aliases) `zip` repeat e+ Union{..} -> HashMap.unions $ NE.toList $ extractBindings <$> options+ f@Fixed{..} -> HashMap.fromList $ (name : aliases) `zip` repeat f+ Array{..} -> extractBindings item+ Map{..} -> extractBindings values+ _ -> HashMap.empty -- | Merge two schemas to produce a third. -- Specifically, @overlay schema reference@ fills in 'NamedTypes' in 'schema' using any matching definitions from 'reference'.
test/Avro/SchemaSpec.hs view
@@ -1,13 +1,17 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} module Avro.SchemaSpec where +import qualified Data.HashMap.Lazy as HashMap+import qualified Data.HashSet as HashSet+ import Data.Avro import Data.Avro.Deriving (makeSchema)-import Data.Avro.Schema (overlay, matches)+import Data.Avro.Schema (extractBindings, matches, overlay) import Test.Hspec @@ -15,6 +19,25 @@ spec :: Spec spec = describe "Avro.SchemaSpec" $ do+ describe "extractBindings" $+ it "should extract bindings for all internal types" $ do+ let schema = $(makeSchema "test/data/internal-bindings.avsc")+ bindings = extractBindings schema+ expected =+ [ "InternalBindings"+ , "InField"+ , "NestedInField"+ , "AliasNestedInField"+ , "NestedEnum"+ , "NestedFixed"+ , "InArray"+ , "NestedInArray"+ , "InMap"+ , "NestedInMap"+ , "InUnionA"+ , "InUnionB"+ ]+ HashSet.fromMap (() <$ bindings) == expected describe "overlay" $ it "should support merging multiple schemas" $ do let expected = $(makeSchema "test/data/overlay/expectation.avsc")
+ test/data/internal-bindings.avsc view
@@ -0,0 +1,105 @@+{+ "name" : "InternalBindings",+ "type" : "record",+ "doc" : "A test record that includes subdefinitions nested in different ways.",+ "fields" : [+ {+ "name" : "inField",+ "doc" : "A record definition nested in a field of a record.",+ "type" : {+ "name" : "InField",+ "type" : "record",+ "fields" : [+ {+ "name" : "nestedInField",+ "doc" : "A record definition nested in two other records.",+ "type" : {+ "name" : "NestedInField",+ "type" : "record",+ "aliases" : ["AliasNestedInField"],+ "fields" : []+ }+ },+ {+ "name" : "nestedEnum",+ "doc" : "An enum definition nested in a nested record.",+ "type" : {+ "type" : "enum",+ "name" : "NestedEnum",+ "symbols" : ["Foo", "Bar"]+ }+ },+ {+ "name" : "nestedFixed",+ "doc" : "A fixed definition nested in a nested record.",+ "type" : {+ "type" : "fixed",+ "size" : 42,+ "name" : "NestedFixed"+ }+ }+ ]+ }+ },+ {+ "name" : "inArray",+ "doc" : "A record definition nested in an array type.",+ "type" : {+ "type" : "array",+ "items" : {+ "name" : "InArray",+ "type" : "record",+ "fields" : [+ {+ "name" : "nestedInArray",+ "doc" : "A record definition nested inside a record defined in an array.",+ "type" : {+ "name" : "NestedInArray",+ "type" : "record",+ "fields" : []+ }+ }+ ]+ }+ }+ },+ {+ "name" : "inMap",+ "doc" : "A record definition nested in a map type.",+ "type" : {+ "type" : "map",+ "values" : {+ "name" : "InMap",+ "type" : "record",+ "fields" : [+ {+ "name" : "nestedInMap",+ "doc" : "A record definition nested inside a record defined in a map.",+ "type" : {+ "name" : "NestedInMap",+ "type" : "record",+ "fields" : []+ }+ }+ ]+ }+ }+ },+ {+ "name" : "inUnion",+ "doc" : "Record definitions nested in a union.",+ "type" : [+ {+ "name" : "InUnionA",+ "type" : "record",+ "fields" : []+ },+ {+ "name" : "InUnionB",+ "type" : "record",+ "fields" : []+ }+ ]+ }+ ]+}