-- |

-- Module:      Data.ProtoBuf.FieldNumber

-- Copyright:   (c) 2015-2016 Martijn Rijkeboer <mrr@sru-systems.com>

-- License:     MIT

-- Maintainer:  Martijn Rijkeboer <mrr@sru-systems.com>

--

-- FieldNumber type and functions.


module Data.ProtoBuf.FieldNumber
    ( FieldNumber(..)
    , fromFieldNumber
    , toFieldNumber
    ) where


import Data.Bits (shiftL, shiftR)
import Data.Word (Word32)


-- | Type to represent a field number (unique numbered tag).

newtype FieldNumber = FieldNumber Word32
    deriving (Int -> FieldNumber -> ShowS
[FieldNumber] -> ShowS
FieldNumber -> String
(Int -> FieldNumber -> ShowS)
-> (FieldNumber -> String)
-> ([FieldNumber] -> ShowS)
-> Show FieldNumber
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FieldNumber] -> ShowS
$cshowList :: [FieldNumber] -> ShowS
show :: FieldNumber -> String
$cshow :: FieldNumber -> String
showsPrec :: Int -> FieldNumber -> ShowS
$cshowsPrec :: Int -> FieldNumber -> ShowS
Show, FieldNumber -> FieldNumber -> Bool
(FieldNumber -> FieldNumber -> Bool)
-> (FieldNumber -> FieldNumber -> Bool) -> Eq FieldNumber
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FieldNumber -> FieldNumber -> Bool
$c/= :: FieldNumber -> FieldNumber -> Bool
== :: FieldNumber -> FieldNumber -> Bool
$c== :: FieldNumber -> FieldNumber -> Bool
Eq, Eq FieldNumber
Eq FieldNumber
-> (FieldNumber -> FieldNumber -> Ordering)
-> (FieldNumber -> FieldNumber -> Bool)
-> (FieldNumber -> FieldNumber -> Bool)
-> (FieldNumber -> FieldNumber -> Bool)
-> (FieldNumber -> FieldNumber -> Bool)
-> (FieldNumber -> FieldNumber -> FieldNumber)
-> (FieldNumber -> FieldNumber -> FieldNumber)
-> Ord FieldNumber
FieldNumber -> FieldNumber -> Bool
FieldNumber -> FieldNumber -> Ordering
FieldNumber -> FieldNumber -> FieldNumber
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: FieldNumber -> FieldNumber -> FieldNumber
$cmin :: FieldNumber -> FieldNumber -> FieldNumber
max :: FieldNumber -> FieldNumber -> FieldNumber
$cmax :: FieldNumber -> FieldNumber -> FieldNumber
>= :: FieldNumber -> FieldNumber -> Bool
$c>= :: FieldNumber -> FieldNumber -> Bool
> :: FieldNumber -> FieldNumber -> Bool
$c> :: FieldNumber -> FieldNumber -> Bool
<= :: FieldNumber -> FieldNumber -> Bool
$c<= :: FieldNumber -> FieldNumber -> Bool
< :: FieldNumber -> FieldNumber -> Bool
$c< :: FieldNumber -> FieldNumber -> Bool
compare :: FieldNumber -> FieldNumber -> Ordering
$ccompare :: FieldNumber -> FieldNumber -> Ordering
$cp1Ord :: Eq FieldNumber
Ord)


instance Num FieldNumber where
    (FieldNumber Word32
x) + :: FieldNumber -> FieldNumber -> FieldNumber
+ (FieldNumber Word32
y) = Word32 -> FieldNumber
FieldNumber (Word32
x Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
y)
    (FieldNumber Word32
x) * :: FieldNumber -> FieldNumber -> FieldNumber
* (FieldNumber Word32
y) = Word32 -> FieldNumber
FieldNumber (Word32
x Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
y)
    abs :: FieldNumber -> FieldNumber
abs (FieldNumber Word32
x)               = Word32 -> FieldNumber
FieldNumber (Word32 -> Word32
forall a. Num a => a -> a
abs Word32
x)
    negate :: FieldNumber -> FieldNumber
negate (FieldNumber Word32
x)            = Word32 -> FieldNumber
FieldNumber (Word32 -> Word32
forall a. Num a => a -> a
negate Word32
x)
    signum :: FieldNumber -> FieldNumber
signum (FieldNumber Word32
x)            = Word32 -> FieldNumber
FieldNumber (Word32 -> Word32
forall a. Num a => a -> a
signum Word32
x)
    fromInteger :: Integer -> FieldNumber
fromInteger Integer
i                     = Word32 -> FieldNumber
FieldNumber (Integer -> Word32
forall a. Num a => Integer -> a
fromInteger Integer
i)


-- | Convert a FieldNumber into a Word32.

fromFieldNumber :: FieldNumber -> Word32
fromFieldNumber :: FieldNumber -> Word32
fromFieldNumber (FieldNumber Word32
n) = Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftL Word32
n Int
3


-- | Convert a Word32 into a FieldNumber or an error.

toFieldNumber :: Word32 -> Either String FieldNumber
toFieldNumber :: Word32 -> Either String FieldNumber
toFieldNumber Word32
i
    | Word32
fn Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0                    = String -> Either String FieldNumber
forall a b. a -> Either a b
Left String
"Invalid FieldNumber 0"
    | Word32
fn Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word32
19000 Bool -> Bool -> Bool
&& Word32
fn Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word32
19999 = String -> Either String FieldNumber
forall a b. a -> Either a b
Left String
"Reserved FieldNumber"
    | Bool
otherwise                  = FieldNumber -> Either String FieldNumber
forall a b. b -> Either a b
Right (FieldNumber -> Either String FieldNumber)
-> FieldNumber -> Either String FieldNumber
forall a b. (a -> b) -> a -> b
$ Word32 -> FieldNumber
FieldNumber Word32
fn
  where fn :: Word32
fn = Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
shiftR Word32
i Int
3