packages feed

isobmff-builder 0.2.0.3 → 0.3.0.0

raw patch · 13 files changed

+816/−284 lines, 13 filesdep +binarydep +hspecdep +isobmff-builderPVP ok

version bump matches the API change (PVP)

Dependencies added: binary, hspec, isobmff-builder, singletons, vector-sized

API changes (from Hackage documentation)

- Data.ByteString.IsoBaseFileFormat.Boxes.Box: (^-) :: (IsBoxType t, IsBoxContent (Boxes t ts)) => ParentBox t -> Boxes t ts -> Box t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: BoxFlags :: Integer -> BoxFlags bits
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: BoxVersion :: Word8 -> BoxVersion
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: Extend :: a -> b -> Extend a b
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: FullBoxHeader :: BoxVersion -> (BoxFlags 24) -> FullBoxHeader
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: UnverifiedBoxes :: (Boxes t ts) -> UnverifiedBoxes t ts
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: [:-] :: IsBoxType t => Boxes c ts -> Box t -> Boxes c (t : ts)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: [Box] :: (IsBoxType t, IsBoxContent c) => BoxType -> c -> Box t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: [ParentBox] :: (IsBoxType t, IsBoxContent c) => BoxType -> c -> ParentBox t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: box :: forall t c. (IsBoxType t, IsBoxContent c) => c -> Box t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: boxFlagBitMask :: KnownNat bits => BoxFlags bits -> Integer
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: boxes :: (IsBoxType t, IsBoxContent (Boxes t ts)) => ParentBox t -> Boxes t ts -> Box t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: class BoxRules t => IsBoxType (t :: k)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: cropBits :: KnownNat bits => BoxFlags bits -> BoxFlags bits
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: data Box (b :: t)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: data Extend a b
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: data FullBoxHeader
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: data ParentBox (b :: t)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: emptyBox :: forall t. (IsBoxType t) => Box t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: emptyParentBox :: forall t. (IsBoxType t) => ParentBox t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: fullBox :: (IsBoxType t, IsBoxContent c) => BoxVersion -> BoxFlags 24 -> c -> Box t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: infixr 1 ^-
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance (Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules t, GHC.TypeLits.KnownSymbol t) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance (Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent p, Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent c) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.Box.Extend p c)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent Data.ByteString.IsoBaseFileFormat.Boxes.Box.FullBoxHeader
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance GHC.TypeLits.KnownNat bits => Data.Bits.Bits (Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxFlags bits)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance GHC.TypeLits.KnownNat bits => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxFlags bits)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall k (bits :: k). GHC.Classes.Eq (Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxFlags bits)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall k (bits :: k). GHC.Num.Num (Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxFlags bits)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall k (bits :: k). GHC.Show.Show (Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxFlags bits)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall t (t1 :: t). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.Box.Box t1)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall x (t :: x) (bs :: [x]). (Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType t, Data.ByteString.IsoBaseFileFormat.Boxes.Box.ValidBoxes t bs) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.Box.Boxes t bs)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall x (t :: x) (bs :: [x]). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.Box.UnverifiedBoxes t bs)
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: newtype BoxFlags bits
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: newtype BoxVersion
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: newtype UnverifiedBoxes t ts
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: parentBox :: forall t c. (IsBoxType t, IsBoxContent c) => c -> ParentBox t
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: toBoxType :: IsBoxType t => proxy t -> BoxType
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: type FullBox t = Extend FullBoxHeader t
- Data.ByteString.IsoBaseFileFormat.Boxes.FileType: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules "ftyp"
- Data.ByteString.IsoBaseFileFormat.Boxes.FileType: type FileTypeBox = Box "ftyp"
- Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: MediaData :: ByteString -> MediaData
- Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules "mdat"
- Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent Data.ByteString.IsoBaseFileFormat.Boxes.MediaData.MediaData
- Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: newtype MediaData
- Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: type MediaDataBox = Box "mdat"
- Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules "moov"
- Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: type MovieBox = Box "moov"
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: ProgressiveDownloadInformation :: Word32 -> Word32 -> ProgressiveDownloadInformation
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: [pdinDelay] :: ProgressiveDownloadInformation -> Word32
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: [pdinRate] :: ProgressiveDownloadInformation -> Word32
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: data ProgressiveDownloadInformation
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules "pdin"
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation.ProgressiveDownloadInformation
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: progressiveDownloadInformationBox :: ProgressiveDownloadInformation -> ProgressiveDownloadInformationBox
- Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: type ProgressiveDownloadInformationBox = Box "pdin"
- Data.ByteString.IsoBaseFileFormat.Boxes.Skip: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules "skip"
- Data.ByteString.IsoBaseFileFormat.Boxes.Skip: type SkipBox = Box "skip"
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: [:.] :: Boxes ts -> Box' t -> Boxes (t : ts)
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: [Box'] :: (IsBoxType' b, ValidBoxes b ts) => BoxContent b -> Boxes ts -> Box' b
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: class (IsBoxContent (BoxContent t), BoxRules t) => IsBoxType' t where type BoxContent t type BoxContent t = () where {
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: closedBox :: (IsBoxType' t, ValidBoxes t '[]) => BoxContent t -> Box' t
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: containerBox :: (IsBoxType' t, ValidBoxes t ts, BoxContent t ~ ()) => Boxes ts -> Box' t
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: data Box' b
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent Data.ByteString.Internal.ByteString
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall k (bs :: [k]). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.Box.Boxes bs)
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: instance forall k (cnt :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.Box.Box' cnt)
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: mediaFile :: Boxes ts -> Builder
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: toBoxType' :: IsBoxType' t => proxy t -> BoxType
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: type BoxContent t = ();
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: (<+>) :: a -> b -> Extend a b
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: Extend :: a -> b -> Extend a b
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: Scalar :: scalartype -> Scalar scalartype
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: [Constant] :: Constant o v
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: [Custom] :: o -> Template o v
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: [Default] :: Template o v
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: [ScalarArray] :: Vector n o -> ScalarArray label n o
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: class FromTypeLit o v
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: data Constant o v
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: data Extend a b
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: data Template o v
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: fromList :: forall label n o. (KnownSymbol label, KnownNat n) => [o] -> ScalarArray label n o
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: fromTypeLit :: FromTypeLit o v => proxy o v -> o
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i16 :: Int16 -> I16 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i16Arr :: (KnownNat size, KnownSymbol label) => [Int16] -> I16Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i32 :: Int32 -> I32 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i32Arr :: (KnownNat size, KnownSymbol label) => [Int32] -> I32Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i64 :: Int64 -> I64 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i64Arr :: (KnownNat size, KnownSymbol label) => [Int64] -> I64Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i8 :: Int8 -> I8 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: i8Arr :: (KnownNat size, KnownSymbol label) => [Int8] -> I8Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance (Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent p, Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent c) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Extend p c)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (arr :: [GHC.Types.Nat]) o (len :: GHC.Types.Nat) (label :: k). (Data.Singletons.SingI arr, GHC.Num.Num o, Data.Singletons.SingKind [GHC.Types.Nat], GHC.TypeLits.KnownNat len, len ~ Data.Singletons.Prelude.List.Length arr) => Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.FromTypeLit (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.ScalarArray label len o) arr
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Int.Int16 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Int.Int32 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Int.Int64 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Int.Int8 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Word.Word16 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Word.Word32 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Word.Word64 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (label :: k). Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar GHC.Word.Word8 label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k (scalar :: GHC.Types.Nat) o (label :: k). (GHC.TypeLits.KnownNat scalar, GHC.Num.Num o) => Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.FromTypeLit (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar o label) scalar
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k o (label :: k) (len :: GHC.Types.Nat). (GHC.Num.Num o, Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar o label), GHC.TypeLits.KnownNat len) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.ScalarArray label len o)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k o (v :: k). (Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent o, Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.FromTypeLit o v) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Constant o v)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall k o (v :: k). (Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent o, Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.FromTypeLit o v) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Template o v)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall scalartype k (label :: k). GHC.Classes.Eq scalartype => GHC.Classes.Eq (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar scalartype label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall scalartype k (label :: k). GHC.Classes.Ord scalartype => GHC.Classes.Ord (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar scalartype label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall scalartype k (label :: k). GHC.Num.Num scalartype => GHC.Num.Num (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar scalartype label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall scalartype k (label :: k). GHC.Read.Read scalartype => GHC.Read.Read (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar scalartype label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: instance forall scalartype k (label :: k). GHC.Show.Show scalartype => GHC.Show.Show (Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields.Scalar scalartype label)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: newtype Scalar scalartype (label :: k)
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: newtype ScalarArray (label :: k) (len :: Nat) o
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type (:+) a b = Extend a b
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I16 label = Scalar Int16 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I16Arr label size = ScalarArray label size Int16
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I32 label = Scalar Int32 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I32Arr label size = ScalarArray label size Int32
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I64 label = Scalar Int64 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I64Arr label size = ScalarArray label size Int64
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I8 label = Scalar Int8 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type I8Arr label size = ScalarArray label size Int8
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U16 label = Scalar Word16 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U16Arr label size = ScalarArray label size Word16
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U32 label = Scalar Word32 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U32Arr label size = ScalarArray label size Word32
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U64 label = Scalar Word64 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U64Arr label size = ScalarArray label size Word64
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U8 label = Scalar Word8 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: type U8Arr label size = ScalarArray label size Word8
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u16 :: Word16 -> U16 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u16Arr :: (KnownNat size, KnownSymbol label) => [Word16] -> U16Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u32 :: Word32 -> U32 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u32Arr :: (KnownNat size, KnownSymbol label) => [Word32] -> U32Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u64 :: Word64 -> U64 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u64Arr :: (KnownNat size, KnownSymbol label) => [Word64] -> U64Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u8 :: Word8 -> U8 label
+ Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields: u8Arr :: (KnownNat size, KnownSymbol label) => [Word8] -> U8Arr label size
+ Data.ByteString.IsoBaseFileFormat.Boxes.FileType: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules Data.ByteString.IsoBaseFileFormat.Boxes.FileType.FileType
+ Data.ByteString.IsoBaseFileFormat.Boxes.FileType: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' Data.ByteString.IsoBaseFileFormat.Boxes.FileType.FileType
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: BoxFlags :: Integer -> BoxFlags bits
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: [V0] :: IsBoxContent v0 => v0 -> Versioned v0 v1 0
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: [V1] :: IsBoxContent v1 => v1 -> Versioned v0 v1 1
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: closedFullBox :: (IsBoxType' t, ValidBoxes t '[], BoxContent t ~ FullBox version c) => BoxVersion version -> BoxFlags 24 -> c -> Box' t
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: data FullBox version t
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: data Versioned v0 v1 (version :: Nat)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: fullBox :: (IsBoxType' t, ValidBoxes t ts, BoxContent t ~ FullBox version c) => BoxVersion version -> BoxFlags 24 -> c -> Boxes ts -> Box' t
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: instance (GHC.TypeLits.KnownNat version, Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent t) => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.FullBox.FullBox version t)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.FullBox.Versioned v0 v1 version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: instance GHC.TypeLits.KnownNat bits => Data.Bits.Bits (Data.ByteString.IsoBaseFileFormat.Boxes.FullBox.BoxFlags bits)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: instance GHC.TypeLits.KnownNat bits => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.FullBox.BoxFlags bits)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: instance forall k (bits :: k). GHC.Classes.Eq (Data.ByteString.IsoBaseFileFormat.Boxes.FullBox.BoxFlags bits)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: instance forall k (bits :: k). GHC.Num.Num (Data.ByteString.IsoBaseFileFormat.Boxes.FullBox.BoxFlags bits)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: instance forall k (bits :: k). GHC.Show.Show (Data.ByteString.IsoBaseFileFormat.Boxes.FullBox.BoxFlags bits)
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: newtype BoxFlags bits
+ Data.ByteString.IsoBaseFileFormat.Boxes.FullBox: type BoxVersion v = Template (U8 "fullbox-version") v
+ Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: data MediaData
+ Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules Data.ByteString.IsoBaseFileFormat.Boxes.MediaData.MediaData
+ Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' Data.ByteString.IsoBaseFileFormat.Boxes.MediaData.MediaData
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: [MovieHeader] :: KnownNat version => ((((((Versioned MovieHeaderTimesV0 MovieHeaderTimesV1 version :+ Template (I32 "rate") 65536) :+ Template (I16 "volume") 256) :+ Constant (I16 "reserved") 0) :+ Constant (I32Arr "reserved" 2) '[0, 0]) :+ Constant (I32Arr "matrix" 9) '[65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824]) :+ Template (U32Arr "pre_defined" 6) '[0, 0, 0, 0, 0, 0]) :+ U32 "next_track_ID" -> MovieHeader version
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: [TrackHeader] :: (((((((Versioned TrackHeaderTimesV0 TrackHeaderTimesV1 version :+ Constant (I32Arr "reserved" 2) '[0, 0]) :+ Template (I16 "layer") 0) :+ Template (I16 "alternate_group") 0) :+ Template (I16 "volume") 256) :+ Constant (I16 "reserved") 0) :+ Template (I32Arr "matrix" 9) '[65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824]) :+ I32 "width") :+ I32 "height" -> TrackHeader version
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: data Movie (version :: Nat)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: data MovieHeader (version :: Nat)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: data Track (version :: Nat)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: data TrackHeader (version :: Nat)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.Movie version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.MovieHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.Track version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.TrackHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.MovieHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxContent (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.TrackHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.Movie version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.Track version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance GHC.TypeLits.KnownNat version => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.MovieHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: instance GHC.TypeLits.KnownNat version => Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' (Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox.TrackHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: movieHeaderBox :: KnownNat version => MovieHeader version -> Box' (MovieHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: track :: ValidBoxes (Track version) ts => Boxes ts -> Box' (Track version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: trackHeader :: KnownNat version => TrackHeader version -> Box' (TrackHeader version)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: type MovieHeaderTimes uint = ((uint "creation_time" :+ uint "modification_time") :+ U32 "timescale") :+ uint "duration"
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: type MovieHeaderTimesV0 = MovieHeaderTimes (Scalar Word32)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: type MovieHeaderTimesV1 = MovieHeaderTimes (Scalar Word64)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: type TrackHeaderTimes uint = (((uint "creation_time" :+ uint "modification_time") :+ U32 "track_ID") :+ Constant (U32 "reserved") 0) :+ uint "duration"
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: type TrackHeaderTimesV0 = TrackHeaderTimes (Scalar Word32)
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: type TrackHeaderTimesV1 = TrackHeaderTimes (Scalar Word64)
+ Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: data ProgressiveDownload
+ Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation.ProgressiveDownload
+ Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation.ProgressiveDownload
+ Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: pdinBox :: ProgressiveDownloadContent -> Box' ProgressiveDownload
+ Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation: type ProgressiveDownloadContent = U32 "rate" :+ U32 "delay"
+ Data.ByteString.IsoBaseFileFormat.Boxes.Skip: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.BoxRules Data.ByteString.IsoBaseFileFormat.Boxes.Skip.Skip
+ Data.ByteString.IsoBaseFileFormat.Boxes.Skip: instance Data.ByteString.IsoBaseFileFormat.Boxes.Box.IsBoxType' Data.ByteString.IsoBaseFileFormat.Boxes.Skip.Skip
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: [Nested] :: IsBoxType t => Box t -> Boxes c '[t]
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: [Nested] :: Boxes '[]
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: data Boxes (cont :: x) (boxTypes :: [x])
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: data Boxes (boxTypes :: [k])
- Data.ByteString.IsoBaseFileFormat.Boxes.Box: type ValidBoxes t ts = (AllAllowedIn t ts ~ True, HasAllRequiredBoxes t (RequiredNestedBoxes t) ts ~ True, CheckTopLevelOk t ~ True)
+ Data.ByteString.IsoBaseFileFormat.Boxes.Box: type ValidBoxes t ts = (AllAllowedIn t ts ~ True, HasAllRequiredBoxes t (RequiredNestedBoxes t) ts ~ True)
- Data.ByteString.IsoBaseFileFormat.Boxes.FileType: fileTypeBox :: FileType -> FileTypeBox
+ Data.ByteString.IsoBaseFileFormat.Boxes.FileType: fileTypeBox :: FileType -> Box' FileType
- Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: mediaDataBox :: MediaData -> MediaDataBox
+ Data.ByteString.IsoBaseFileFormat.Boxes.MediaData: mediaDataBox :: ByteString -> Box' MediaData
- Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: movieBox :: ParentBox "moov"
+ Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox: movieBox :: ValidBoxes (Movie version) ts => Boxes ts -> Box' (Movie version)
- Data.ByteString.IsoBaseFileFormat.Boxes.Skip: skipBox :: Skip -> SkipBox
+ Data.ByteString.IsoBaseFileFormat.Boxes.Skip: skipBox :: Skip -> Box' Skip

Files

isobmff-builder.cabal view
@@ -1,5 +1,5 @@ name:                isobmff-builder-version:             0.2.0.3+version:             0.3.0.0 synopsis:            A (bytestring-) builder for the ISO-14496-12 base media file format description:         Please see README.md homepage:            https://github.com/sheyll/isobmff-builder#readme@@ -17,7 +17,9 @@   hs-source-dirs:      src   exposed-modules:     Data.ByteString.IsoBaseFileFormat.Builder                      , Data.ByteString.IsoBaseFileFormat.Boxes.Box+                     , Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields                      , Data.ByteString.IsoBaseFileFormat.Boxes.FileType+                     , Data.ByteString.IsoBaseFileFormat.Boxes.FullBox                      , Data.ByteString.IsoBaseFileFormat.Boxes.MediaData                      , Data.ByteString.IsoBaseFileFormat.Boxes.Skip                      , Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation@@ -25,7 +27,11 @@   build-depends:       base >= 4.9 && < 5                      , bytestring >= 0.10.8.1                      , type-list >= 0.5.0.0+                     -- , mtl+                     , vector-sized >= 0.3.2.0+                     , singletons >= 2.2   default-language:    Haskell2010+  ghc-options:       -Wall -funbox-strict-fields -fno-warn-unused-do-bind   default-extensions:  ConstraintKinds                      , CPP                      , DataKinds@@ -52,6 +58,50 @@                      , TypeInType                      , TypeOperators                      , TypeSynonymInstances++test-suite spec+  type:                exitcode-stdio-1.0+  ghc-options:         -Wall+  hs-source-dirs:      spec+  default-language:    Haskell2010+  main-is:             Spec.hs+  other-modules:       BoxFieldsSpec+                     , BoxSpec+  build-depends:       base >= 4.9 && < 5+                     , bytestring >= 0.10.8.1+                     , hspec+                     , isobmff-builder+                     , binary+  default-language:    Haskell2010+  default-extensions:  ConstraintKinds+                     , CPP+                     , DataKinds+                     , DefaultSignatures+                     , DeriveDataTypeable+                     , DeriveFunctor+                     , DeriveGeneric+                     , FlexibleInstances+                     , FlexibleContexts+                     , FunctionalDependencies+                     , GADTs+                     , GeneralizedNewtypeDeriving+                     , KindSignatures+                     , MultiParamTypeClasses+                     , OverloadedStrings+                     , QuasiQuotes+                     , RecordWildCards+                     , RankNTypes+                     , ScopedTypeVariables+                     , StandaloneDeriving+                     , TemplateHaskell+                     , TupleSections+                     , TypeFamilies+                     , TypeInType+                     , TypeOperators+                     , TypeSynonymInstances+  ghc-options:       -Wall -O0 -j +RTS -A256m -n2m -RTS+                     -fwarn-unused-binds -fno-warn-unused-do-bind -fno-warn-missing-signatures+ source-repository head   type:     git   location: https://github.com/githubuser/isobmff-builder
+ spec/BoxFieldsSpec.hs view
@@ -0,0 +1,76 @@+module BoxFieldsSpec (spec) where++import Test.Hspec+import Data.ByteString.IsoBaseFileFormat.Builder+-- import qualified Data.ByteString.Builder as B+import qualified Data.ByteString.Lazy as BL+-- import qualified Data.Binary.Get as Binary+import Control.Exception (evaluate)++-- import qualified Data.ByteString.Builder as B import qualified Data.ByteString.Lazy as BL import+-- qualified Data.Binary.Get as Binary++spec :: Spec+spec =+  describe "Scalar, Constant, Template and ScalarArry composition" $+  describe "IsBoxContent instances" $+  do describe "example1" $+       do it "boxSize reports the correct size" $+             boxSize example1 `shouldBe` (1 + 1 + (3 * 8) + (7 * 8))+          it "crashes during rendering because of the invalid number of array elements for \"baz\"" $+             evaluate (renderBox example1') `shouldThrow` anyException+     describe "example2" $+       do it "boxSize reports the correct size" $+             boxSize example2 `shouldBe` (2 * 4 + 2 + 2 + 2 + 2 + 9 * 4 + 4 + 4)+          it "it renders the expected content" $+             renderBox example2 `shouldBe` (BL.pack [0,0,0,0,+                                                     0,0,0,0,+                                                        0,65,+                                                        0,66,+                                                         1,0,+                                                         0,0,+                                                     0,0,0,67,+                                                     0,0,0,68,+                                                     0,0,0,69,+                                                     0,0,0,70,+                                                     0,0,0,71,+                                                     0,0,0,72,+                                                     0,0,0,73,+                                                     0,0,0,74,+                                                     0,0,0,75,+                                                     0,0,0,76,+                                                     0,0,0,77])++renderBox :: IsBoxContent c => c -> BL.ByteString+renderBox = toLazyByteString . boxBuilder++type ExampleContent = Scalar Word8 "bla" :+ Constant (Scalar Word8 "blub") 123 :+ Template (ScalarArray "foos" 3 Int64) '[1, 2, 3] :+ ScalarArray "baz" 7 Word64++type ExampleContentShort = U8 "bla" :+ Constant (U8 "blub") 123 :+ Template (I64Arr "foos" 3) '[1, 2, 3] :+ U64Arr "baz" 7++example1 :: ExampleContent+example1 = Scalar 100 <+> Constant <+> Default <+> u64Arr [1,2,3]++example1' :: ExampleContentShort+example1' = example1++type Example2 isAudio =+     Constant (I32Arr "reserved" 2) '[0, 0]+  :+ Template (I16 "layer") 0+  :+ Template (I16 "alternate_group") 0+  :+ Template (I16 "volume") (If isAudio 256 0)+  :+ Constant (I16 "reserved") 0+  :+ Template (I32Arr "matrix" 9) '[65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824]+  :+ I32 "width"+  :+ I32 "height"++example2 :: Example2 'True+example2 =+  Constant <+>+  Custom 65 <+>+  Custom 66 <+>+  Default <+>+  Constant <+>+  Custom (i32Arr [67 .. 75]) <+>+  i32 76 <+>+  i32 77
+ spec/BoxSpec.hs view
@@ -0,0 +1,57 @@+module BoxSpec (spec) where++import Test.Hspec+import Data.ByteString.IsoBaseFileFormat.Builder+import qualified Data.ByteString.Builder as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.Binary.Get as Binary++spec :: Spec+spec =+  do describe "IsBoxContent instances" $+       do describe "()" $+            do describe "boxSize" $ it "returns 0" $ boxSize () `shouldBe` 0+               describe "boxBuilder" $+                 it "emits no data" $+                 BL.length (B.toLazyByteString (boxBuilder ())) `shouldBe` 0+          describe "Box" $+            do describe "boxSize" $+                 it "returns the header size if the content is empty" $+                 boxSize testBox1 `shouldBe` (4 + 4)+          describe "Boxes" $+            do describe "boxSize" $+                 do describe "a box with one nested box" $+                      do it "returns the sum of both boxSizes" $+                           boxSize (testParentBox1 $ Nested :. testBox1) `shouldBe`+                           (2 * boxSize testBox1)+                         it "returns the same value as written by boxBuilder" $+                           let b = testParentBox1 $ Nested :. testBox1+                               writtenSize =+                                 let out = toLazyByteString (boxBuilder b)+                                     getSize = Binary.runGet Binary.getWord32be+                                 in BoxSize $ fromIntegral $ getSize out+                               reportedSize = boxSize b+                           in writtenSize `shouldBe` reportedSize+++data TestBox1++instance BoxRules TestBox1 where+  type RestrictedTo TestBox1 = 'Nothing++instance IsBoxType' TestBox1 where+  toBoxType' _ = StdType "tst1"++testBox1 :: Box' TestBox1+testBox1 = closedBox ()+++data TestParentBox1++instance BoxRules TestParentBox1++instance IsBoxType' TestParentBox1 where+  toBoxType' _ = StdType "par1"++testParentBox1 :: (ValidBoxes TestParentBox1 ts) => Boxes ts -> Box' TestParentBox1+testParentBox1 = containerBox
+ spec/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
src/Data/ByteString/IsoBaseFileFormat/Boxes/Box.hs view
@@ -20,16 +20,20 @@ import GHC.TypeLits as X import Data.String import Data.Type.Equality- import Data.Type.List import Data.Type.Bool-import Data.Type.Equality-import GHC.Exts+import qualified Data.ByteString as B  -- * Basic Types and classes +-- | Base class for all (abstract/phantom/normal-) types that represent boxes+class (IsBoxContent (BoxContent t), BoxRules t) => IsBoxType' t where+  type BoxContent t+  type BoxContent t = ()+  toBoxType' :: proxy t -> BoxType+ -- | A class that describes (on the type level) how a box can be nested into--- other boxes (see 'Boxes').+-- other boxes (see 'Boxes). class BoxRules (t :: k) where   -- | List of boxes that this box can be nested into.   type RestrictedTo t :: Maybe [k]@@ -43,18 +47,11 @@   type RequiredNestedBoxes t = '[]   -- | Describes how many times a box should be present in a container (-box).   type GetCardinality t (c :: k) :: Cardinality-  type GetCardinality t any = ExactlyOnce+  type GetCardinality t any = 'ExactlyOnce  -- | Describes how many times a box should be present in a container. data Cardinality = AtMostOnce | ExactlyOnce | OnceOrMore --- | Convert type level box types to values-class BoxRules t => IsBoxType (t :: k) where-  toBoxType :: proxy t -> BoxType--instance (BoxRules t, KnownSymbol t) => IsBoxType t where-  toBoxType _ = StdType (fromString (symbolVal (Proxy :: Proxy t)))- -- | Types that go into a box. A box content is a piece of data that can be -- reused in different instances of 'IsBox'. It has no 'BoxType' and hence -- defines no box.@@ -62,49 +59,56 @@   boxSize :: a -> BoxSize   boxBuilder :: a -> Builder --- | An empty box content can by represented by @()@ (i.e. /unit/).-instance IsBoxContent () where-  boxSize _ = 0-  boxBuilder _ = mempty+-- * Data types --- | Box content composed of box contents @a@ and @b@.-data Extend a b =-  Extend a-         b+-- | A type that wraps the contents of a box and the box type.+data Box' b where+  Box' :: (IsBoxType' b, ValidBoxes b ts) => BoxContent b -> Boxes ts -> Box' b -instance (IsBoxContent p,IsBoxContent c) => IsBoxContent (Extend p c) where-  boxSize (Extend p c) = boxSize p + boxSize c-  boxBuilder (Extend p c) = boxBuilder p <> boxBuilder c+instance IsBoxContent (Box' cnt) where+  boxBuilder b@(Box' cnt nested) = sB <> tB <> sExtB <> tExtB <> cntB <> nestedB+    where s       = boxSize    b+          t       = toBoxType' b+          sB      = boxBuilder s+          sExtB   = boxBuilder (BoxSizeExtension s)+          tB      = boxBuilder t+          tExtB   = boxBuilder (BoxTypeExtension t)+          cntB    = boxBuilder cnt+          nestedB = boxBuilder nested --- * Boxes+  boxSize b@(Box' cnt nested) = sPayload + boxSize (BoxSizeExtension sPayload)+    where sPayload =   boxSize (BoxSize undefined)+                     + boxSize t+                     + boxSize cnt+                     + boxSize (BoxTypeExtension t)+                     + boxSize nested+          t        = toBoxType' b --- | Create a 'Box' from any 'IsBoxContent' with a type.-box :: forall t c.-       (IsBoxType t,IsBoxContent c)-    => c -> Box t-box cnt = Box (toBoxType (Proxy :: Proxy t)) cnt+-- | A heterogenous collection of boxes.+data Boxes (boxTypes :: [k]) where+        Nested :: Boxes '[]+        (:.) :: Boxes ts -> Box' t -> Boxes (t ': ts) --- | An /empty/ box. This is for boxes without any extra /fields/. Although it is--- called /emptyBox/ it might still contain nested boxes.-emptyBox :: forall t . (IsBoxType t) => Box t-emptyBox = box ()+infixl 2 :. --- | A type that wraps the contents of a box and the box type.-data Box (b :: t) where-        Box :: (IsBoxType t,IsBoxContent c) => BoxType -> c -> Box t+instance IsBoxContent (Boxes bs) where+  boxSize Nested = 0+  boxSize (bs :. b) = boxSize bs + boxSize b+  boxBuilder Nested = mempty+  boxBuilder (bs :. b) = boxBuilder bs <> boxBuilder b -instance IsBoxContent (Box t) where-  boxBuilder b@(Box t cnt) = sFix <> tFix <> sExt <> tExt <> boxBuilder cnt-    where s = boxSize b-          sFix = boxBuilder s-          sExt = boxBuilder (BoxSizeExtension s)-          tFix = boxBuilder t-          tExt = boxBuilder (BoxTypeExtension t)-  boxSize b@(Box t cnt) = sPayload + boxSize (BoxSizeExtension sPayload)-    where sPayload =-            boxSize sPayload + boxSize t + boxSize cnt +-            boxSize (BoxTypeExtension t)+-- | A box that contains no nested boxes.+closedBox :: (IsBoxType' t, ValidBoxes t '[]) => BoxContent t -> Box' t+closedBox c = Box' c Nested +-- | A box that contains no fields, but nested boxes.+containerBox :: (IsBoxType' t, ValidBoxes t ts, BoxContent t ~ ()) => Boxes ts -> Box' t+containerBox = Box' ()++-- | A complete media file, consisting of top-level boxes.+mediaFile :: Boxes ts -> Builder+mediaFile = boxBuilder+ -- * Box Size and Type  -- | The size of the box. If the size is limited to a (fixed) value, it can be@@ -121,7 +125,7 @@   boxBuilder UnlimitedSize = word32BE 0   boxBuilder (BoxSize n) =     word32BE $-    if n < 2 ^ 32+    if n < (4294967296 :: Word64)        then fromIntegral n        else 1 @@ -149,13 +153,13 @@ instance IsBoxContent BoxSizeExtension where   boxBuilder (BoxSizeExtension UnlimitedSize) = mempty   boxBuilder (BoxSizeExtension (BoxSize n)) =-    if n < 2 ^ 32+    if n < 4294967296        then mempty        else word64BE n   boxSize (BoxSizeExtension UnlimitedSize) = 0   boxSize (BoxSizeExtension (BoxSize n)) =     BoxSize $-    if n < 2 ^ 32+    if n < 4294967296        then 0        else 8 @@ -194,7 +198,7 @@   boxBuilder t =     case t of       StdType x -> boxBuilder x-      CustomBoxType u -> boxBuilder (FourCc ('u','u','i','d'))+      CustomBoxType _ -> boxBuilder (FourCc ('u','u','i','d'))  -- | When using custom types extra data must be written after the extra size -- information. Since the box type and the optional custom box type are not@@ -213,82 +217,14 @@  -- * Type-safe box composition --- | A 'ParentBox' is a 'Box' but without it's children. It has no--- 'IsBoxContent' instance, and it must be converted to a real 'Box' using--- 'boxes'. This is to prevent creation of boxes with invalid children.-data ParentBox (b :: t) where-        ParentBox :: (IsBoxType t,IsBoxContent c) => BoxType -> c -> ParentBox t --- | A parent box. Similar to 'box' but for 'ParentBox'es.-parentBox :: forall t c . (IsBoxType t, IsBoxContent c) => c -> ParentBox t-parentBox = toParentBox . box-  where toParentBox :: IsBoxType s => Box s -> ParentBox s-        toParentBox (Box t c) = ParentBox t c---- | A 'ParentBox' without /fields/.-emptyParentBox :: forall t . (IsBoxType t) => ParentBox t-emptyParentBox = parentBox ()---- | A box that containing nested boxes. The nesting is validated at compile--- time using 'BoxRules'. -boxes :: (IsBoxType t,IsBoxContent (Boxes t ts))-      => ParentBox t -> Boxes t ts -> Box t-boxes p = box . Extend (toBox p)-  where-    toBox :: IsBoxType t => ParentBox t -> Box t-    toBox (ParentBox t c) = Box t c---- | An operator for starting a 'Boxes' from the parent box.------ Example:--- >  xxx :: Box "moov"--- >  xxx = movieBox--- >         ^- Nested (movieHeaderBox (MovieHeader ...))--- >                   :- (trackBox--- >                       ^- Nested (trackHeaderBox (TrackHeader ...))--- >                                 :- trackReferenceBox (TrackReference ...)--- >                                 :- trackGroupingIndication (TrackGroupingInd ...))----(^-) :: (IsBoxType t,IsBoxContent (Boxes t ts))-     => ParentBox t -> Boxes t ts -> Box t-parent ^- nested = parent ^- nested--infixr 1 ^----- | A heterogenous collection of child boxes for a parent box wiht type @cont@.-data Boxes (cont :: x) (boxTypes :: [x]) where-        Nested :: IsBoxType t => Box t -> Boxes c '[t]-        (:-) :: IsBoxType t => Boxes c ts -> Box t -> Boxes c (t ': ts)--infixl 2 :----- | To be nested into a box, 'Boxes' must be an instance of 'IsBoxContent'.--- This instance concatenates all nested boxes.-instance (IsBoxType t,ValidBoxes t bs) => IsBoxContent (Boxes t bs) where-  boxSize bs = boxSize (UnverifiedBoxes bs)-  boxBuilder bs = boxBuilder (UnverifiedBoxes bs)---- | An internal wrapper type around 'Boxes' for the 'IsBoxContent' instance.--- Since the 'IsBoxContent' instance recursivly deconstructs a 'Boxes' the--- constraints for the validity 'ValidBoxes' cannot be asserted. To circumvent--- this the 'IsBoxContent' instance for 'Boxes' delegates to the instance of--- 'UnverifiedBoxes', which has no 'ValidBoxes' constraint in the instance head.-newtype UnverifiedBoxes t ts = UnverifiedBoxes (Boxes t ts)--instance IsBoxContent (UnverifiedBoxes t bs) where-  boxSize (UnverifiedBoxes (Nested b)) = boxSize b-  boxSize (UnverifiedBoxes (bs :- b)) = boxSize (UnverifiedBoxes bs) + boxSize b-  boxBuilder (UnverifiedBoxes (Nested b)) = boxBuilder b-  boxBuilder (UnverifiedBoxes (bs :- b)) = boxBuilder (UnverifiedBoxes bs) <> boxBuilder b- -- * Type level consistency checks  -- | A type-level check that uses 'BoxRules' to check that the contained boxes -- are standard conform. type ValidBoxes t ts =   ( AllAllowedIn t ts ~ 'True-  , HasAllRequiredBoxes t (RequiredNestedBoxes t) ts ~ 'True-  , CheckTopLevelOk t ~ 'True)+  , HasAllRequiredBoxes t (RequiredNestedBoxes t) ts ~ 'True )  -- | A type function to check that all nested boxes are allowed in the -- container.@@ -307,18 +243,18 @@  -- | The custom (type-) error message for 'AllAllowedIn'. type NotAllowedMsg c t =-  Text "Boxes of type: "-  :<>: ShowType c-  :<>: Text " may not contain boxes of type "-  :<>: ShowType t-  :$$: Text "Valid containers for "-  :<>: ShowType t-  :<>: Text " boxes are: "-  :$$: ShowType (RestrictedTo t)-  :$$: ShowType t-  :<>: If (IsTopLevelBox c)-          (Text " boxes may appear top-level in a file.")-          (Text " boxes must be nested.")+  'Text "Boxes of type: "+  ':<>: 'ShowType c+  ':<>: 'Text " may not contain boxes of type "+  ':<>: 'ShowType t+  ':$$: 'Text "Valid containers for "+  ':<>: 'ShowType t+  ':<>: 'Text " boxes are: "+  ':$$: 'ShowType (RestrictedTo t)+  ':$$: 'ShowType t+  ':<>: If (IsTopLevelBox c)+          ('Text " boxes may appear top-level in a file.")+          ('Text " boxes must be nested.")   -- | Check that all required boxes have been nested.@@ -332,103 +268,43 @@  type IsSubSet base sub = Intersection base sub == sub --- | The custom (type-) error message for 'HasAllRequiredBoxes'.+-- | The custom (type-) error message for 'HasAllRequiredBoxes. type MissingRequired c r nested =-  Text "Boxes of type: "-  :<>: ShowType c-  :<>: Text " require these nested boxes: "-  :<>: ShowType (RequiredNestedBoxes c)-  :$$: Text "but only these box types were nested: "-  :<>: ShowType nested-  :$$: Text "e.g. this type is missing: "-  :<>: ShowType r+  'Text "Boxes of type: "+  ':<>: 'ShowType c+  ':<>: 'Text " require these nested boxes: "+  ':<>: 'ShowType (RequiredNestedBoxes c)+  ':$$: 'Text "but only these box types were nested: "+  ':<>: 'ShowType nested+  ':$$: 'Text "e.g. this type is missing: "+  ':<>: 'ShowType r +-- | Check that all boxes may appear top-level.+type family CheckAllTopLevelOk (ts :: [k]) :: Bool where+   CheckAllTopLevelOk '[] = 'True+   CheckAllTopLevelOk (t ': rest) = CheckTopLevelOk t && CheckAllTopLevelOk rest+ -- | Check that the box may appear top-level. type family CheckTopLevelOk (t :: k) :: Bool where    CheckTopLevelOk t = IsTopLevelBox t || TypeError (NotTopLevenError t) + -- | The custom (type-) error message indicating that a box may not appear -- top-level. type NotTopLevenError c =-       Text "Boxes of type "-  :<>: ShowType c-  :<>: Text " MUST be nested inside boxes of these types: "-  :$$: ShowType (RestrictedTo c)---- * Full Boxes---- | A `Box` with /version/ and /branding/ information-type FullBox t = Extend FullBoxHeader t---- | Create a 'FullBox' from a 'FourCc' 'StdType' and the nested box content.-fullBox- :: (IsBoxType t, IsBoxContent c)- => BoxVersion -> BoxFlags 24 -> c -> Box t-fullBox ver fs cnt = box (Extend (FullBoxHeader ver fs) cnt)---- | The additional header with /version/ and /branding/ information-data FullBoxHeader =-  FullBoxHeader BoxVersion-                (BoxFlags 24)--instance IsBoxContent FullBoxHeader where-  boxSize (FullBoxHeader _ f) = 1 + boxSize f-  boxBuilder (FullBoxHeader (BoxVersion v) f) = word8 v <> boxBuilder f---- | The box version (in a 'FullBox') is a single byte-newtype BoxVersion =-  BoxVersion Word8---- | In addition to a 'BoxVersion' there can be 24 bits for custom flags etc in--- a 'FullBox'.-newtype BoxFlags bits =-  BoxFlags Integer-  deriving (Eq,Show,Num)---- | Internal function that creates a bit mask with all bits in a 'BoxFlags' set--- to 1.-boxFlagBitMask :: KnownNat bits-               => BoxFlags bits -> Integer-boxFlagBitMask px = 2 ^ natVal px - 1+        'Text "Boxes of type "+  ':<>: 'ShowType c+  ':<>: 'Text " MUST be nested inside boxes of these types: "+  ':$$: 'ShowType (RestrictedTo c) --- | Internal function that masks-out all bits higher than 'bits'.-cropBits :: KnownNat bits-         => BoxFlags bits -> BoxFlags bits-cropBits f@(BoxFlags b) = BoxFlags (b .&. boxFlagBitMask f)+-- * 'IsBoxContent' instances --- | Get the number of bytes required to store a number of bits.-instance KnownNat bits => IsBoxContent (BoxFlags bits) where-  boxSize f =-    let minBytes = fromInteger $ natVal f `div` 8-        modBytes = fromInteger $ natVal f `mod` 8-    in BoxSize $ minBytes + signum modBytes-  boxBuilder f@(BoxFlags b) =-    let bytes =-          let (BoxSize bytes') = boxSize f-          in fromIntegral bytes'-        wordSeq n-          | n <= bytes =-            word8 (fromIntegral (shiftR b ((bytes - n) * 8) .&. 255)) <>-            wordSeq (n + 1)-          | otherwise = mempty-    in wordSeq 1+-- | An empty box content can by represented by @()@ (i.e. /unit/).+instance IsBoxContent () where+  boxSize _ = 0+  boxBuilder _ = mempty -instance KnownNat bits => Bits (BoxFlags bits) where-  (.&.) lf@(BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ l .&. r-  (.|.) lf@(BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ l .&. r-  xor (BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ xor l r-  complement (BoxFlags x) = cropBits $ BoxFlags $ complement x-  shift (BoxFlags x) = cropBits . BoxFlags . shift x-  rotateL = error "TODO rotateL"-  rotateR = error "TODO rotateR"-  bitSize = fromInteger . natVal-  bitSizeMaybe = Just . fromInteger . natVal-  isSigned _ = False-  testBit f n =-    let (BoxFlags b) = cropBits f-    in testBit b n-  bit = cropBits . BoxFlags . bit-  popCount f =-    let (BoxFlags b) = cropBits f-    in popCount b-  zeroBits = BoxFlags 0+-- | Trivial instance for 'ByteString'+instance IsBoxContent B.ByteString where+  boxSize = fromIntegral . B.length+  boxBuilder = byteString
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/BoxFields.hs view
@@ -0,0 +1,239 @@+-- | Mini EDSL for labelled box fields. The boxfields can be 'Scalar' or+-- 'ScalarArray's.+module Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields+       where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box+import Data.Int+import Data.Maybe+import Text.Printf+import Data.Singletons+import Data.Singletons.Prelude.List+import qualified Data.Vector.Sized as Vec++-- * Scalar box fields++type U64 label = Scalar Word64 label++type I64 label = Scalar Int64 label++u64 :: Word64 -> U64 label+u64 = Scalar++i64 :: Int64 -> I64 label+i64 = Scalar++type U32 label = Scalar Word32 label++type I32 label = Scalar Int32 label++u32 :: Word32 -> U32 label+u32 = Scalar++i32 :: Int32 -> I32 label+i32 = Scalar++type U16 label = Scalar Word16 label++type I16 label = Scalar Int16 label++u16 :: Word16 -> U16 label+u16 = Scalar++i16 :: Int16 -> I16 label+i16 = Scalar++type U8 label = Scalar Word8 label++type I8 label = Scalar Int8 label++u8 :: Word8 -> U8 label+u8 = Scalar++i8 :: Int8 -> I8 label+i8 = Scalar++-- | A numeric box field with a type level label. Note that it has a 'Num'+-- instance. Use the type aliases above, e.g.+-- 'U8','I8','U16','I16','U32','I32','U64','I64' from above. Use either the+-- smart constructors, e.g. 'u8','i8','u16','i16','u32','i32','u64','i64' or the+-- 'Num' instance, whereas the constructors might give a bit more safety.+newtype Scalar scalartype (label :: k) =+  Scalar scalartype deriving (Show, Read, Ord, Eq, Num)++instance IsBoxContent (Scalar Word8 label) where+  boxSize _ = 1+  boxBuilder (Scalar v) = word8 v++instance IsBoxContent (Scalar Word16 label) where+  boxSize _ = 2+  boxBuilder (Scalar v) = word16BE v++instance IsBoxContent (Scalar Word32 label) where+  boxSize _ = 4+  boxBuilder (Scalar v) = word32BE v++instance IsBoxContent (Scalar Word64 label) where+  boxSize _ = 8+  boxBuilder (Scalar v) = word64BE v++instance IsBoxContent (Scalar Int8 label) where+  boxSize _ = 1+  boxBuilder (Scalar v) = int8 v++instance IsBoxContent (Scalar Int16 label) where+  boxSize _ = 2+  boxBuilder (Scalar v) = int16BE v++instance IsBoxContent (Scalar Int32 label) where+  boxSize _ = 4+  boxBuilder (Scalar v) = int32BE v++instance IsBoxContent (Scalar Int64 label) where+  boxSize _ = 8+  boxBuilder (Scalar v) = int64BE v++instance (KnownNat scalar,Num o) => FromTypeLit (Scalar o label) scalar where+  fromTypeLit _ = Scalar $ fromIntegral $ natVal (Proxy :: Proxy scalar)++-- * Array fields++type U64Arr label size = ScalarArray label size Word64++u64Arr :: (KnownNat size,KnownSymbol label)+       => [Word64] -> U64Arr label size+u64Arr = fromList++type I64Arr label size = ScalarArray label size Int64++i64Arr :: (KnownNat size,KnownSymbol label)+       => [Int64] -> I64Arr label size+i64Arr = fromList++type U32Arr label size = ScalarArray label size Word32++u32Arr :: (KnownNat size,KnownSymbol label)+       => [Word32] -> U32Arr label size+u32Arr = fromList++type I32Arr label size = ScalarArray label size Int32++i32Arr :: (KnownNat size,KnownSymbol label)+       => [Int32] -> I32Arr label size+i32Arr = fromList++type U16Arr label size = ScalarArray label size Word16++u16Arr :: (KnownNat size,KnownSymbol label)+       => [Word16] -> U16Arr label size+u16Arr = fromList++type I16Arr label size = ScalarArray label size Int16++i16Arr :: (KnownNat size,KnownSymbol label)+       => [Int16] -> I16Arr label size+i16Arr = fromList++type U8Arr label size = ScalarArray label size Word8++u8Arr :: (KnownNat size,KnownSymbol label)+      => [Word8] -> U8Arr label size+u8Arr = fromList++type I8Arr label size = ScalarArray label size Int8++i8Arr :: (KnownNat size,KnownSymbol label)+      => [Int8] -> I8Arr label size+i8Arr = fromList++-- | A box field that is an array of 'Scalar's with a type level label. Use the+-- type aliases, e.g.+-- 'U8Arr','I8Arr','U16Arr','I16Arr','U32Arr','I32Arr','U64Arr','I64Arr' from+-- above. Use the smart constructors, e.g.+-- 'u8Arr','i8Arr','u16Arr','i16Arr','u32Arr','i32Arr','u64Arr','i64Arr' .+newtype ScalarArray (label :: k) (len :: Nat) o where+        ScalarArray :: Vec.Vector n o -> ScalarArray label n o++instance (Num o,IsBoxContent (Scalar o label),KnownNat (len :: Nat)) => IsBoxContent (ScalarArray label len o) where+  boxSize (ScalarArray vec) =+    fromIntegral (Vec.length vec) * boxSize (Scalar 0 :: Scalar o label)+  boxBuilder (ScalarArray vec) =+    Vec.foldl' mappend+               mempty+               (Vec.map (boxBuilder . mkScalar) vec)+    where mkScalar :: o -> Scalar o label+          mkScalar = Scalar++-- | Internal function+fromList :: forall label n o.+            (KnownSymbol label,KnownNat n)+         => [o] -> ScalarArray label n o+fromList l =+  ScalarArray $+  case Vec.fromList l of+    Nothing ->+      error $+      printf "Invalid number of array elements for array %s. Got length: %d elments, expected %d."+             (show (symbolVal (Proxy :: Proxy label)))+             (length l)+             (natVal (Proxy :: Proxy n))+    Just v -> v++-- * Constant fields++-- | Wrapper around a field, e.g. a 'Scalar' or 'ScalarArray', with a type level+-- value. The wrapped content must implement 'FromTypeLit'.+data Constant o v where+        Constant :: Constant o v++instance (IsBoxContent o,FromTypeLit o v) => IsBoxContent (Constant o v) where+  boxSize = boxSize . fromTypeLit+  boxBuilder = boxBuilder . fromTypeLit++-- * Template Fields++-- | Fields with default values that can be overriden with custom value. Like+-- 'Constant' this is a wrapper around a field, e.g. a 'Scalar' or+-- 'ScalarArray', with a type level default value. The wrapped content must+-- implement 'FromTypeLit'.+data Template o v where+        Default :: Template o v+        Custom :: o -> Template o v++instance (IsBoxContent o,FromTypeLit o v) => IsBoxContent (Template o v) where+  boxSize = boxSize . fromTypeLit+  boxBuilder d@Default = boxBuilder $ fromTypeLit d+  boxBuilder (Custom o) = boxBuilder o++-- * Conversion from type-level numbers and lists to values++-- | Types that can be constructed from type level value representations.+class FromTypeLit o v  where+  fromTypeLit :: proxy o v -> o++instance (SingI arr,Num o,SingKind [Nat],KnownNat len,len ~ Length arr) => FromTypeLit (ScalarArray label len o) (arr :: [Nat]) where+  fromTypeLit _ =+    let s = sing :: Sing arr+        vs :: [Integer]+        vs = fromSing s+        vs' :: [o]+        vs' = fromIntegral <$> vs+    in ScalarArray (fromJust (Vec.fromList vs'))++-- * Box concatenation++-- | Box content composition+data Extend a b =+  Extend a+         b++-- | An operator for 'Extend'.+type a :+ b = Extend a b++-- | An operator for 'Extend'.+(<+>) :: a -> b -> Extend a b+(<+>) = Extend++instance (IsBoxContent p,IsBoxContent c) => IsBoxContent (Extend p c) where+  boxSize (Extend p c) = boxSize p + boxSize c+  boxBuilder (Extend p c) = boxBuilder p <> boxBuilder c
src/Data/ByteString/IsoBaseFileFormat/Boxes/FileType.hs view
@@ -3,14 +3,17 @@ import Data.ByteString.IsoBaseFileFormat.Boxes.Box  -- | File Type Box-type FileTypeBox = Box "ftyp" -instance BoxRules "ftyp"+instance BoxRules FileType +instance IsBoxType' FileType where+  type BoxContent FileType = FileType+  toBoxType' _ = StdType "ftyp"+ -- | Create a 'FileTypeBox' from a major brand, a minor version and a list of -- compatible brands-fileTypeBox :: FileType -> FileTypeBox-fileTypeBox = box+fileTypeBox :: FileType -> Box' FileType+fileTypeBox = closedBox  -- | Contents of a 'ftyp' box are some 'FourCc' /brands/ and a version. data FileType =@@ -19,6 +22,7 @@            ,compatibleBrands :: [FourCc]}  instance IsBoxContent FileType where-  boxSize (FileType maj ver comps) = boxSize maj + 4 + sum (boxSize <$> comps)+  boxSize (FileType maj _ver comps) =+    boxSize maj + 4 + sum (boxSize <$> comps)   boxBuilder (FileType maj ver comps) =     boxBuilder maj <> word32BE ver <> mconcat (boxBuilder <$> comps)
+ src/Data/ByteString/IsoBaseFileFormat/Boxes/FullBox.hs view
@@ -0,0 +1,99 @@+-- | Full Boxes+module Data.ByteString.IsoBaseFileFormat.Boxes.FullBox+       (FullBox(), fullBox, closedFullBox, BoxVersion, BoxFlags(..), Versioned(..)) where++import Data.ByteString.IsoBaseFileFormat.Boxes.Box+import Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields++-- | A 'FullBox' contains an extra version and a flags field. In this+-- implementation it is wrapped around the rest of the box content. This+-- enforces that the 'FullBox' header fields are always at the beginning - at+-- least as long as this module hides the 'FullBox' constructor ;)+data FullBox version t where+        FullBox ::+          BoxVersion version -> BoxFlags 24 -> t -> FullBox version t++instance (KnownNat version,IsBoxContent t) => IsBoxContent (FullBox version t) where+  boxSize (FullBox _ f c) = 1 + boxSize f + boxSize c+  boxBuilder (FullBox v f c) = boxBuilder v <> boxBuilder f <> boxBuilder c++-- | Create a 'FullBox' from a 'BoxVersion' and 'BoxFlags'+fullBox+  :: (IsBoxType' t,ValidBoxes t ts,BoxContent t ~ FullBox version c)+  => BoxVersion version -> BoxFlags 24 -> c -> Boxes ts -> Box' t+fullBox version fs cnt = Box' (FullBox version fs cnt)++-- | Create a 'FullBox' from a 'BoxVersion' and 'BoxFlags' without nested boxes.+closedFullBox+  :: (IsBoxType' t,ValidBoxes t '[],BoxContent t ~ FullBox version c)+  => BoxVersion version -> BoxFlags 24 -> c -> Box' t+closedFullBox version fs cnt = closedBox (FullBox version fs cnt)++-- | The box version (in a 'FullBox') is a single byte+type BoxVersion v = Template (U8 "fullbox-version") v++-- | Two alternative representations based on a /version/ index.+--   Use this for box content that can be either 32 or 64 bit.+data Versioned v0 v1 (version :: Nat) where+  V0 :: IsBoxContent v0 => v0 -> Versioned v0 v1 0+  V1 :: IsBoxContent v1 => v1 -> Versioned v0 v1 1++instance IsBoxContent (Versioned v0 v1 version) where+  boxSize (V0 c) = boxSize c+  boxSize (V1 c) = boxSize c+  boxBuilder (V0 c) = boxBuilder c+  boxBuilder (V1 c) = boxBuilder c++-- | In addition to a 'BoxVersion' there can be 24 bits for custom flags etc in+-- a 'FullBox'.+newtype BoxFlags bits =+  BoxFlags Integer+  deriving (Eq,Show,Num)++-- | Internal function that creates a bit mask with all bits in a 'BoxFlags' set+-- to 1.+boxFlagBitMask :: KnownNat bits+               => BoxFlags bits -> Integer+boxFlagBitMask px = 2 ^ natVal px - 1++-- | Internal function that masks-out all bits higher than 'bits'.+cropBits :: KnownNat bits+         => BoxFlags bits -> BoxFlags bits+cropBits f@(BoxFlags b) = BoxFlags (b .&. boxFlagBitMask f)++-- | Get the number of bytes required to store a number of bits.+instance KnownNat bits => IsBoxContent (BoxFlags bits) where+  boxSize f =+    let minBytes = fromInteger $ natVal f `div` 8+        modBytes = fromInteger $ natVal f `mod` 8+    in BoxSize $ minBytes + signum modBytes+  boxBuilder f@(BoxFlags b) =+    let bytes =+          let (BoxSize bytes') = boxSize f+          in fromIntegral bytes'+        wordSeq n+          | n <= bytes =+            word8 (fromIntegral (shiftR b ((bytes - n) * 8) .&. 255)) <>+            wordSeq (n + 1)+          | otherwise = mempty+    in wordSeq 1++instance KnownNat bits => Bits (BoxFlags bits) where+  (.&.) (BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ l .&. r+  (.|.) (BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ l .&. r+  xor (BoxFlags l) (BoxFlags r) = cropBits $ BoxFlags $ xor l r+  complement (BoxFlags x) = cropBits $ BoxFlags $ complement x+  shift (BoxFlags x) = cropBits . BoxFlags . shift x+  rotateL = error "TODO rotateL"+  rotateR = error "TODO rotateR"+  bitSize = fromInteger . natVal+  bitSizeMaybe = Just . fromInteger . natVal+  isSigned _ = False+  testBit f n =+    let (BoxFlags b) = cropBits f+    in testBit b n+  bit = cropBits . BoxFlags . bit+  popCount f =+    let (BoxFlags b) = cropBits f+    in popCount b+  zeroBits = BoxFlags 0
src/Data/ByteString/IsoBaseFileFormat/Boxes/MediaData.hs view
@@ -4,18 +4,15 @@ import qualified Data.ByteString as B  -- | Media data box-type MediaDataBox = Box "mdat"--instance BoxRules "mdat"+data MediaData --- | Create a 'MediaDataBox' from a strict 'ByteString'-mediaDataBox :: MediaData -> MediaDataBox-mediaDataBox = box+instance BoxRules MediaData --- | Contents of a 'mdat' box are just bytes from a strict 'ByteString'-newtype MediaData =-  MediaData B.ByteString+instance IsBoxType' MediaData where+  -- | Contents of a 'mdat' box are just bytes from a strict 'ByteString'+  type BoxContent MediaData = B.ByteString+  toBoxType' _ = StdType "mdat" -instance IsBoxContent MediaData where-  boxSize (MediaData bs) = fromIntegral $ B.length bs-  boxBuilder (MediaData bs) = byteString bs+-- | Create a 'MediaDataBox' from a strict 'ByteString'+mediaDataBox :: B.ByteString -> Box' MediaData+mediaDataBox = closedBox
src/Data/ByteString/IsoBaseFileFormat/Boxes/MovieBox.hs view
@@ -1,32 +1,156 @@+{-# LANGUAGE UndecidableInstances #-}+ -- | Meta data for a presentation of a /movie/. module Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox where  import Data.ByteString.IsoBaseFileFormat.Boxes.Box--- Uncomment this to see what the custom compiler errors look like:+import Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields+import Data.ByteString.IsoBaseFileFormat.Boxes.FullBox++-- | Compose a set of boxes into a 'MovieBox' ---import Data.ByteString.IsoBaseFileFormat.Boxes.Skip+-- Example:+--+-- >  xxx :: Box' Movie+-- >  xxx = movieBox $+-- >         Nested (movieHeaderBox (...))+-- >         :. (trackBox $+-- >              Nested (trackHeaderBox (TrackHeader ...))+-- >              :. trackReferenceBox (TrackReference ...)+-- >              :. trackGroupingIndication (TrackGroupingInd ...))+--+movieBox :: ValidBoxes (Movie version) ts+         => Boxes ts -> Box' (Movie version)+movieBox = containerBox --- xxx :: Box "moov"--- xxx = movieBox---         (movieBoxContainer :- skipBox (Skip 100))--- | The metadata for a presentation, a single 'MovieBox' which occurs only once+-- | The metadata for a presentation, a single 'Movie' which occurs only once -- and top-level. It is pretty empty on it's own, but it contains nested boxes -- with all the relevant meta data.-type MovieBox = Box "moov"+data Movie (version :: Nat) -instance BoxRules "moov" where-  type RequiredNestedBoxes "moov" = '["mvhd", "trak"]+instance IsBoxType' (Movie version) where+  toBoxType' _ = StdType "moov" --- | A movie parent box. Combine with the nested 'Boxes' using 'boxes' or '(^-)'------ Example:--- >  xxx :: Box "moov"--- >  xxx = movieBox--- >         ^- Nested (movieHeaderBox (MovieHeader ...))--- >                   :- (trackBox--- >                       ^- Nested (trackHeaderBox (TrackHeader ...))--- >                                 :- trackReferenceBox (TrackReference ...)--- >                                 :- trackGroupingIndication (TrackGroupingInd ...))----movieBox :: ParentBox "moov"-movieBox = emptyParentBox+instance BoxRules (Movie version) where+  type RequiredNestedBoxes (Movie version) = '[MovieHeader version]++-- * @mvhd@ Box++-- | Construct a 'MovieHeader' box.+movieHeaderBox+  :: KnownNat version+  => MovieHeader version -> Box' (MovieHeader version)+movieHeaderBox = closedFullBox Default 0++-- | Movie meta data, indexed by a version.+data MovieHeader (version :: Nat) where+        MovieHeader ::+            KnownNat version =>+               Versioned MovieHeaderTimesV0+                         MovieHeaderTimesV1+                         version+            :+ Template (I32 "rate") 0x00010000+            :+ Template (I16 "volume") 0x0100+            :+ Constant (I16 "reserved") 0+            :+ Constant (I32Arr "reserved" 2) '[0,0]+            :+ Constant (I32Arr "matrix" 9)+                        '[65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824]+            :+ Template (U32Arr "pre_defined" 6) '[0,0,0,0,0,0]+            :+ U32 "next_track_ID"+            -> MovieHeader version++-- | Time and timing information about a movie (32bit version).+type MovieHeaderTimesV0 = MovieHeaderTimes (Scalar Word32)++-- | Time and timing information about a movie (64bit version).+type MovieHeaderTimesV1 = MovieHeaderTimes (Scalar Word64)++-- | Time and timing information about a movie.+type MovieHeaderTimes uint =+      uint "creation_time"+   :+ uint "modification_time"+   :+ U32 "timescale"+   :+ uint "duration"++instance IsBoxContent (MovieHeader version) where+  boxSize (MovieHeader c) = boxSize c+  boxBuilder (MovieHeader c) = boxBuilder c++instance KnownNat version => IsBoxType' (MovieHeader version) where+  toBoxType' _ = StdType "mvhd"+  type BoxContent (MovieHeader version) = FullBox version (MovieHeader version)++instance BoxRules (MovieHeader version) where+  type IsTopLevelBox (MovieHeader version) = 'False+  type GetCardinality (MovieHeader version) any = 'ExactlyOnce+  type RestrictedTo (MovieHeader version) = 'Just '[Movie version]++-- * @trak@ Box++-- | Compose a 'Track' box from the given boxes.+track :: ValidBoxes (Track version) ts+      => Boxes ts -> Box' (Track version)+track = containerBox++-- | Container box for tracks.+data Track (version :: Nat)++instance IsBoxType' (Track version) where+  toBoxType' _ = StdType "trak"++instance BoxRules (Track version) where+  type IsTopLevelBox (Track version) = 'False+  type GetCardinality (Track version) any = 'ExactlyOnce+  type RestrictedTo (Track version) = 'Just '[Movie version]++-- * @tkhd@ Box+++-- | Create a 'TrackHeader' box.+trackHeader+  :: KnownNat version => TrackHeader version -> Box' (TrackHeader version)+trackHeader = closedFullBox Default 0++-- | Track meta data, indexed by a version.+data TrackHeader (version :: Nat) where+        TrackHeader ::+               Versioned TrackHeaderTimesV0+                         TrackHeaderTimesV1+                         version+            :+ Constant (I32Arr "reserved" 2) '[0, 0]+            :+ Template (I16 "layer") 0+            :+ Template (I16 "alternate_group") 0+            :+ Template (I16 "volume") 256+            :+ Constant (I16 "reserved") 0+            :+ Template (I32Arr "matrix" 9)+                        '[65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824]+            :+ I32 "width"+            :+ I32 "height"+            -> TrackHeader version++-- | Time and timing information about a track (32bit version).+type TrackHeaderTimesV0 = TrackHeaderTimes (Scalar Word32)++-- | Time and timing information about a track (64bit version).+type TrackHeaderTimesV1 = TrackHeaderTimes (Scalar Word64)++-- | Time and timing information about a track.+type TrackHeaderTimes uint =+      uint "creation_time"+   :+ uint "modification_time"+   :+ U32 "track_ID"+   :+ Constant (U32 "reserved") 0+   :+ uint "duration"++instance IsBoxContent (TrackHeader version) where+  boxSize (TrackHeader c) = boxSize c+  boxBuilder (TrackHeader c) = boxBuilder c++instance KnownNat version => IsBoxType' (TrackHeader version) where+  type BoxContent (TrackHeader version) = FullBox version (TrackHeader version)+  toBoxType' _ = StdType "tkhd"++instance BoxRules (TrackHeader version) where+  type IsTopLevelBox (TrackHeader version) = 'False+  type GetCardinality (TrackHeader version) any = 'ExactlyOnce+  type RestrictedTo (TrackHeader version) = 'Just '[Track version]
src/Data/ByteString/IsoBaseFileFormat/Boxes/ProgressiveDownloadInformation.hs view
@@ -2,24 +2,23 @@        where  import Data.ByteString.IsoBaseFileFormat.Boxes.Box+import Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields+import Data.ByteString.IsoBaseFileFormat.Boxes.FullBox  -- | A Box with progressive download information-type ProgressiveDownloadInformationBox = Box "pdin"+data ProgressiveDownload -instance BoxRules "pdin"+instance BoxRules ProgressiveDownload --- | Create a 'pdin' box-progressiveDownloadInformationBox-  :: ProgressiveDownloadInformation -> ProgressiveDownloadInformationBox-progressiveDownloadInformationBox = fullBox (BoxVersion 0) zeroBits+instance IsBoxType' ProgressiveDownload where+  type BoxContent ProgressiveDownload = FullBox 0 ProgressiveDownloadContent+  toBoxType' _ = StdType "pdin"  -- | Information for progressive media data download/playback encompasses the -- delay for initial playback and expected download bit rate.-data ProgressiveDownloadInformation =-  ProgressiveDownloadInformation {pdinRate :: Word32 -- ^ Effective download bitrate in byte/sec-                                 ,pdinDelay :: Word32 -- ^ Delay in milli seconds-                                 }+type ProgressiveDownloadContent = U32 "rate" :+ U32 "delay" -instance IsBoxContent ProgressiveDownloadInformation where-  boxSize _ = 8-  boxBuilder pdin = word32BE (pdinRate pdin) <> word32BE (pdinDelay pdin)+-- | Construct a @pdin@ box.+pdinBox+  :: ProgressiveDownloadContent -> Box' ProgressiveDownload+pdinBox = closedFullBox Default 0
src/Data/ByteString/IsoBaseFileFormat/Boxes/Skip.hs view
@@ -1,20 +1,21 @@+-- | A filler box with a specific size. module Data.ByteString.IsoBaseFileFormat.Boxes.Skip where  import Data.ByteString.IsoBaseFileFormat.Boxes.Box --- | A filler box, the contents are skipped-type SkipBox = Box "skip"+-- | Contents of a 'skip' box are just any number of filler bytes.+newtype Skip = Skip Int -instance BoxRules "skip" where-  type RestrictedTo "skip" = 'Nothing+instance IsBoxType' Skip where+  type BoxContent Skip = Skip+  toBoxType' _ = StdType "skip" --- | Create a 'SkipBox' with a given size.-skipBox :: Skip -> SkipBox-skipBox = box+instance BoxRules Skip where+  type RestrictedTo Skip = 'Nothing --- | Contents of a 'skip' box are just any number of filler bytes.-newtype Skip =-  Skip Int+-- | Create a 'Skip' with a given size.+skipBox :: Skip -> Box' Skip+skipBox = closedBox  instance IsBoxContent Skip where   boxSize (Skip bs) = fromIntegral bs
src/Data/ByteString/IsoBaseFileFormat/Builder.hs view
@@ -1,11 +1,20 @@ -- | This module re-exports all modules needed to build /ISOBMFF/ documents. module Data.ByteString.IsoBaseFileFormat.Builder-  (module Data.ByteString.IsoBaseFileFormat.Builder, module X)+  (module X)   where  import Data.ByteString.IsoBaseFileFormat.Boxes.Box as X+import Data.ByteString.IsoBaseFileFormat.Boxes.BoxFields as X import Data.ByteString.IsoBaseFileFormat.Boxes.FileType as X+import Data.ByteString.IsoBaseFileFormat.Boxes.FullBox as X import Data.ByteString.IsoBaseFileFormat.Boxes.MediaData as X import Data.ByteString.IsoBaseFileFormat.Boxes.MovieBox as X import Data.ByteString.IsoBaseFileFormat.Boxes.ProgressiveDownloadInformation as X import Data.ByteString.IsoBaseFileFormat.Boxes.Skip as X++import Data.Int as X+import Data.Kind as X  (Type, Constraint)+import Data.Maybe as X+import Data.Type.Bool as X+import Data.Type.Equality as X+import Text.Printf as X