ipldm-1.0.0.0: ipld/IPLD/DM.hs
-- | Module : IPLD.DM
-- Description : Provides Node and Kind types for IPLD
-- Copyright : Zoey McBride (c) 2026
-- License : AGPL-3.0-or-later
-- Maintainer : zoeymcbride@mailbox.org
-- Stability : experimental
module IPLD.DM
( -- * Kinds are the data types of the IPLD data model
Kind (..),
-- * Node objects within a DM graph
Node,
-- * Implementing the IPLD bytesring
BytesData (..),
-- * Implementing the IPLD map type
MapData,
-- * Implementing the IPLD list type
ListData,
-- * Stores raw IEEE-754 floating point data.
FloatData (..),
)
where
import Control.DeepSeq (NFData (..))
import Data.Array (Array)
import Data.ByteString.Builder (Builder)
import Data.ByteString.Builder qualified as Builder
import Data.Text (Text)
import Data.Word (Word16, Word32, Word64)
import MultiFormats.CID (CID)
-- | All nodes within the DM have a kind with their, and this is part of the
-- Kind sum-type, so this is just a type-alias.
type Node = Kind
-- | Implements sum type for Kind, the representable data in IPLD.
-- https://ipld.io/docs/data-model/kinds/
-- https://ipld.io/docs/data-model/node/
data Kind
= -- | Null can only have the value `Null`.
-- https://ipld.io/docs/data-model/kinds/#null-kind
NullKind
| -- | True or False.
-- https://ipld.io/docs/data-model/kinds/#boolean-kind
BoolKind Bool
| -- | AKA: Integer. IPLD suggests to use an unlimited size number
-- representation when available, so we use integer. It will be up to the
-- implementer of DataModel whether to use this space or not.
-- https://ipld.io/docs/data-model/kinds/#integer-kind
-- https://ipld.io/design/tricky-choices/numeric-domain/#integers
IntKind Integer
| -- | AKA: Float. This is how we represent decimal numbers with Kind.
-- https://ipld.io/docs/data-model/kinds/#float-kind
-- https://ipld.io/design/tricky-choices/numeric-domain/#floating-point
FloatKind FloatData
| -- | IPLD recommends UTF-8 support, so Text is used.
-- https://ipld.io/docs/data-model/kinds/#string-kind
StringKind Text
| -- | Stores arbitrary bytes of any length.
-- https://ipld.io/docs/data-model/kinds/#bytes-kind
BytesKind BytesData
| -- | AKA: Link, IPLD links data together using Multiformat's Content ID/CID.
-- Using links, we can point to data in another IPLD block.
-- https://ipld.io/docs/data-model/kinds/#link-kind
ResourceKind CID
| -- | Recursive type: List of Nodes.
-- https://ipld.io/docs/data-model/kinds/#list-kind
ListKind (ListData Node)
| -- | Recursive type: Map of Nodes.
-- https://ipld.io/docs/data-model/kinds/#map-kind
MapKind (MapData Node Node)
deriving (Show, Eq)
-- | Fully instantiates a Kind object from lazy Haskell object.
instance NFData Kind where
rnf NullKind = ()
rnf (BoolKind bool) = rnf bool
rnf (IntKind int) = rnf int
rnf (FloatKind float) = rnf float
rnf (BytesKind bytesdata) = rnf bytesdata
rnf (StringKind text) = rnf text
rnf (ResourceKind cid) = rnf cid
rnf (ListKind list) = rnf list
rnf (MapKind kvs) = rnf kvs
-- | New-type for `Builder` for the bytestring type IPLD in data model.
data BytesData = BytesData
{ bytesDataBuilder :: Builder,
bytesDataLength :: Int
}
deriving (Show)
-- | Fully instantiates a BytesData object from lazy Haskell object.
instance NFData BytesData where
rnf (BytesData builder len) = builder `seq` len `seq` ()
-- | Implements `Eq` on `BytesData` by executing `Builder.toLazyByteString` on
-- both inputs.
instance Eq BytesData where
(BytesData b1 l1) == (BytesData b2 l2) =
l1 == l2 && Builder.toLazyByteString b1 == Builder.toLazyByteString b2
-- | Type-alias for storing the map type in the IPLD data model.
type ListData t = Array Int t
-- | Type-alias for storing the map type in the IPLD data model.
type MapData k v = Array Int (k, v)
-- | FloatData stores float types for different sizes.
data FloatData
= -- | Raw IEEE754 half precision data. This doesn't have a Haskell type.
HalfPrecision Word16
| -- | Raw IEEE754 single precision data. Corresponds to Haskell `Float`.
SinglePrecision Word32
| -- | Raw IEEE754 double precision data. Corresponds to Haskell `Double`.
DoublePrecision Word64
deriving (Show, Eq)
-- | Fully instantiates a FloatData object from lazy Haskell object.
instance NFData FloatData where
rnf (HalfPrecision w16) = rnf w16 `seq` ()
rnf (SinglePrecision w32) = rnf w32 `seq` ()
rnf (DoublePrecision w64) = rnf w64 `seq` ()