-- -- Copyright © 2013-2014 Anchor Systems, Pty Ltd and Others -- -- The code in this file, and the program it is a part of, is -- made available to you by its authors as open source software: -- you can redistribute it and/or modify it under the terms of -- the 3-clause BSD licence. -- {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TupleSections #-} module Vaultaire.Types.Address ( Address(..), calculateBucketNumber, isAddressExtended, ) where import Control.Applicative import Data.Bits import Data.Hashable import Data.Locator import Data.Packer (getWord64LE, putWord64LE, runPacking, tryUnpacking) import Data.String import Data.Word (Word64) import Test.QuickCheck import Vaultaire.Classes.WireFormat newtype Address = Address { unAddress :: Word64 } deriving (Eq, Ord, Hashable, Num, Bounded) instance Read Address where readsPrec _ = pure . (,"") . Address . fromInteger . fromBase62 instance Show Address where show = padWithZeros 11 . toBase62 . toInteger . unAddress instance IsString Address where fromString = fromIntegral . fromBase62 -- | There are assumptions made that the encoding of Address is fixed-length (8 -- bytes). Changing that will break things subtly. instance WireFormat Address where toWire = runPacking 8 . putWord64LE . unAddress fromWire = tryUnpacking (Address `fmap` getWord64LE) instance Arbitrary Address where arbitrary = Address <$> arbitrary calculateBucketNumber :: Word64 -> Address -> Word64 calculateBucketNumber num_buckets (Address addr) = (addr `clearBit` 0) `mod` num_buckets isAddressExtended :: Address -> Bool isAddressExtended (Address addr) = addr `testBit` 0