Safe Haskell | None |
---|---|
Language | Haskell2010 |
Definition of the most basic element in an ISOBMFF file: a box. See Chapter 4 in the standard document. A box is a container with a type, a size, some data and some nested boxes. The standard defines - among other characteristics - available box types and their semantics, the fields they contain and how they are nested into each other. This library tries to capture some of these characteristics using modern Haskell type system features, in order to provide compile time checks for (partial) standard compliance.
- class (IsBoxContent (BoxContent t), BoxRules t) => IsBoxType' t where
- type BoxContent t
- class BoxRules t where
- type RestrictedTo t :: Maybe [k]
- type IsTopLevelBox t :: Bool
- type RequiredNestedBoxes t :: [k]
- type GetCardinality t (c :: k) :: Cardinality
- data Cardinality
- class IsBoxContent a where
- data Box' b where
- Box' :: (IsBoxType' b, ValidBoxes b ts) => BoxContent b -> Boxes ts -> Box' b
- data Boxes boxTypes where
- closedBox :: (IsBoxType' t, ValidBoxes t '[]) => BoxContent t -> Box' t
- containerBox :: (IsBoxType' t, ValidBoxes t ts, BoxContent t ~ ()) => Boxes ts -> Box' t
- mediaFile :: Boxes ts -> Builder
- data BoxSize
- data BoxSizeExtension = BoxSizeExtension BoxSize
- data BoxType
- newtype FourCc = FourCc (Char, Char, Char, Char)
- data BoxTypeExtension = BoxTypeExtension BoxType
- type ValidBoxes t ts = (AllAllowedIn t ts ~ True, HasAllRequiredBoxes t (RequiredNestedBoxes t) ts ~ True)
- type family AllAllowedIn (container :: k) (boxes :: [k]) :: Bool where ...
- type family CheckAllowedIn (c :: k) (t :: k) (a :: Maybe [k]) :: Bool where ...
- 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."))
- type family HasAllRequiredBoxes (c :: k) (req :: [k]) (nested :: [k]) :: Bool where ...
- type IsSubSet base sub = Intersection base sub == sub
- 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)
- type family CheckAllTopLevelOk (ts :: [k]) :: Bool where ...
- type family CheckTopLevelOk (t :: k) :: Bool where ...
- type NotTopLevenError c = ((Text "Boxes of type " :<>: ShowType c) :<>: Text " MUST be nested inside boxes of these types: ") :$$: ShowType (RestrictedTo c)
Basic Types and classes
class (IsBoxContent (BoxContent t), BoxRules t) => IsBoxType' t where Source #
Base class for all (abstractphantomnormal-) types that represent boxes
type BoxContent t Source #
toBoxType' :: proxy t -> BoxType Source #
IsBoxType' * FileType Source # | |
IsBoxType' * MediaData Source # | |
IsBoxType' * ProgressiveDownload Source # | |
IsBoxType' * Skip Source # | |
KnownNat version => IsBoxType' * (TrackHeader version) Source # | |
IsBoxType' * (Track version) Source # | |
KnownNat version => IsBoxType' * (MovieHeader version) Source # | |
IsBoxType' * (Movie version) Source # | |
A class that describes (on the type level) how a box can be nested into other boxes (see 'Boxes).
type RestrictedTo t :: Maybe [k] Source #
List of boxes that this box can be nested into.
type IsTopLevelBox t :: Bool Source #
If the box is also allowed 'top-level' i.e. in the file directly, not nested in an other box.
type RequiredNestedBoxes t :: [k] Source #
Describes which nested boxes MUST be present in a box using boxes
.
type GetCardinality t (c :: k) :: Cardinality Source #
Describes how many times a box should be present in a container (-box).
data Cardinality Source #
Describes how many times a box should be present in a container.
class IsBoxContent a where Source #
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.
Data types
A type that wraps the contents of a box and the box type.
Box' :: (IsBoxType' b, ValidBoxes b ts) => BoxContent b -> Boxes ts -> Box' b |
IsBoxContent (Box' k cnt) Source # | |
data Boxes boxTypes where Source #
A heterogenous collection of boxes.
IsBoxContent (Boxes k bs) Source # | |
closedBox :: (IsBoxType' t, ValidBoxes t '[]) => BoxContent t -> Box' t Source #
A box that contains no nested boxes.
containerBox :: (IsBoxType' t, ValidBoxes t ts, BoxContent t ~ ()) => Boxes ts -> Box' t Source #
A box that contains no fields, but nested boxes.
Box Size and Type
The size of the box. If the size is limited to a (fixed) value, it can be
provided as a Word64
which will be represented as either a 32bit compact
size or as 64 bit largesize. If UnlimitedSize
is used, the box extends to
the end of the file.
data BoxSizeExtension Source #
The BoxSize
can be > 2^32 in which case an BoxSizeExtension
must be
added after the type field.
A box has a type, this is the value level representation for the box type.
StdType FourCc |
|
CustomBoxType String | CustomBoxType defines custom |
A type containin a printable four letter character code.
data BoxTypeExtension Source #
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 guaranteed to be consequtive, this type handles the second part seperately.
Type-safe box composition
Type level consistency checks
type ValidBoxes t ts = (AllAllowedIn t ts ~ True, HasAllRequiredBoxes t (RequiredNestedBoxes t) ts ~ True) Source #
A type-level check that uses BoxRules
to check that the contained boxes
are standard conform.
type family AllAllowedIn (container :: k) (boxes :: [k]) :: Bool where ... Source #
A type function to check that all nested boxes are allowed in the container.
AllAllowedIn c '[] = True | |
AllAllowedIn c (t ': ts) = If (CheckAllowedIn c t (RestrictedTo t)) (AllAllowedIn c ts) (TypeError (NotAllowedMsg c t)) |
type family CheckAllowedIn (c :: k) (t :: k) (a :: Maybe [k]) :: Bool where ... Source #
CheckAllowedIn c t Nothing = True | |
CheckAllowedIn c t (Just rs) = Find c rs |
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.")) Source #
The custom (type-) error message for AllAllowedIn
.
type family HasAllRequiredBoxes (c :: k) (req :: [k]) (nested :: [k]) :: Bool where ... Source #
Check that all required boxes have been nested.
HasAllRequiredBoxes c '[] nested = True | |
HasAllRequiredBoxes c (r ': restReq) nested = If (Find r nested) (HasAllRequiredBoxes c restReq nested) (TypeError (MissingRequired c r nested)) |
type IsSubSet base sub = Intersection base sub == sub Source #
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) Source #
The custom (type-) error message for 'HasAllRequiredBoxes.
type family CheckAllTopLevelOk (ts :: [k]) :: Bool where ... Source #
Check that all boxes may appear top-level.
CheckAllTopLevelOk '[] = True | |
CheckAllTopLevelOk (t ': rest) = CheckTopLevelOk t && CheckAllTopLevelOk rest |
type family CheckTopLevelOk (t :: k) :: Bool where ... Source #
Check that the box may appear top-level.
CheckTopLevelOk t = IsTopLevelBox t || TypeError (NotTopLevenError t) |
type NotTopLevenError c = ((Text "Boxes of type " :<>: ShowType c) :<>: Text " MUST be nested inside boxes of these types: ") :$$: ShowType (RestrictedTo c) Source #
The custom (type-) error message indicating that a box may not appear top-level.