packages feed

snowchecked-0.0.0.1: src/Data/Snowchecked/Encoding/Class.hs

{-# LANGUAGE RecordWildCards #-}

module Data.Snowchecked.Encoding.Class ( IsFlake(..), Flakeish(..), goodFish ) where

import           Data.Snowchecked.Internal.Import

{-| Something that might be a 'Flake'.  The fields might not be truncated
 - to the appropriate size.
 -}
data Flakeish = Flakeish
	{ fishNodeId    ::  Word256
	, fishCount     ::  Word256
	, fishTime      ::  Word256
	, fishCheck     ::  Word256
	}

{-| Is this 'Flakeish' valid under the given 'SnowcheckedConfig' settings? -}
goodFish :: SnowcheckedConfig -> Flakeish -> Bool
goodFish SnowcheckedConfig{..} Flakeish{..} =
		checkInteger == cutBits (nodeInteger + countInteger + timeInteger) confCheckBits
	where
		checkInteger = cutBits fishCheck confCheckBits
		nodeInteger = cutBits fishNodeId confNodeBits
		countInteger = cutBits fishCount confCountBits
		timeInteger = cutBits fishTime confTimeBits
{-# INLINEABLE goodFish #-}

{-| The class of things that can be generated from and to a 'Flake'.
 -}
class IsFlake a where
	{-# MINIMAL fromFlake, (parseFish | parseFlake) #-}
	fromFlake :: Flake -> a
	parseFlake :: (MonadFail m) => SnowcheckedConfig -> a -> m Flake
	parseFlake cfg@SnowcheckedConfig{..} a = parseFish cfg a >>= \fish@Flakeish{..} ->
		if goodFish cfg fish then
			return $ Flake
				{ flakeTime = cutBits fishTime confTimeBits
				, flakeCount = cutBits fishCount confCountBits
				, flakeNodeId = cutBits fishNodeId confNodeBits
				, flakeConfig = cfg
				}
		else
			fail "Checksum is incorrect for Snowchecked flake"

	parseFish :: (MonadFail m) => SnowcheckedConfig -> a -> m Flakeish
	parseFish cfg a = toFlakeish <$> parseFlake cfg a
		where
			toFlakeish Flake{..} = Flakeish
				{ fishTime = flakeTime
				, fishCount = flakeCount
				, fishNodeId = flakeNodeId
				, fishCheck = flakeTime + flakeCount + flakeNodeId
				}