builder (empty) → 0.1
raw patch · 5 files changed
+315/−0 lines, 5 filesdep +basedep +byte-orderdep +primitive
Dependencies added: base, byte-order, primitive, primitive-unaligned
Files
- CHANGELOG.md +12/−0
- LICENSE +29/−0
- README.md +7/−0
- builder.cabal +56/−0
- src/Builder.hs +211/−0
+ CHANGELOG.md view
@@ -0,0 +1,12 @@+# Changelog++`builder` uses [PVP Versioning][1].+The changelog is available [on GitHub][2].++0.0.0+=====++* Initially created.++[1]: https://pvp.haskell.org+[2]: https://github.com/chessai/builder/releases
+ LICENSE view
@@ -0,0 +1,29 @@+BSD 3-Clause License++Copyright (c) 2019, chessai+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,7 @@+# builder++[](https://hackage.haskell.org/package/builder)+[](LICENSE)+[](https://travis-ci.org/chessai/builder)++bounded bytearray builder type
+ builder.cabal view
@@ -0,0 +1,56 @@+cabal-version: 2.2+name:+ builder+version:+ 0.1+synopsis:+ bounded ByteArray builder type+description:+ A Builder type for ByteArray. Appending these builders+ can be cheaper than when appending ByteArray values, since+ only one buffer allocation is performed.+homepage:+ https://github.com/chessai/builder+bug-reports:+ https://github.com/chessai/builder/issues+license:+ BSD-3-Clause+license-file:+ LICENSE+author:+ chessai+maintainer:+ chessai <chessai1996@gmail.com>+copyright:+ © 2019 chessai+category:+ Data+build-type:+ Simple+extra-doc-files:+ README.md+ , CHANGELOG.md+tested-with:+ GHC == 8.6.5++library+ hs-source-dirs:+ src+ exposed-modules:+ Builder+ build-depends:+ , base >= 4.11 && < 4.14+ , byte-order >= 0.1.1 && < 0.2+ , primitive >= 0.6.4 && < 0.8+ , primitive-unaligned >= 0.1 && < 0.2+ ghc-options:+ -Wall+ -O2+ default-language:+ Haskell2010++source-repository head+ type:+ git+ location:+ https://github.com/chessai/builder.git
+ src/Builder.hs view
@@ -0,0 +1,211 @@+{-# language+ BangPatterns+ , MagicHash+ , RankNTypes+ , UnboxedTuples+ #-}++-- | A 'Builder' type for 'ByteArray'. Appending these builders+-- can be cheaper than when appending 'ByteArray' values, since+-- you only perform one buffer allocation.+module Builder+ ( -- * Builder type+ Builder++ -- * Consumption+ , build++ -- * Construction+ , buildUnaligned+ , buildWord8+ , buildWord16+ , buildWord32+ , buildWord64+ , buildWord+ , buildInt8+ , buildInt16+ , buildInt32+ , buildInt64+ , buildInt+ , buildFloat+ , buildDouble+ , buildChar+ , buildPtr+ , buildByteArray+ , buildFixed+ ) where++import Data.Primitive hiding (writeByteArray)+import Data.Primitive.ByteArray.Unaligned+import Data.Int+import Data.Word+import GHC.Exts hiding (build)+import System.ByteOrder++newtype Writer s = W+ { _w :: ()+ => MutableByteArray# s+ -- buffer+ -> Int#+ -- offset into buffer+ -> (State# s -> (# State# s, Int# #))+ -- update to offset+ }++instance Semigroup (Writer s) where+ W x <> W y = W $ \marr# ix0# s0# -> case x marr# ix0# s0# of+ (# s1#, ix1# #) -> y marr# ix1# s1#+ {-# inline (<>) #-}++instance Monoid (Writer s) where+ mempty = W $ \_ ix0# s0# -> (# s0#, ix0# #)+ {-# inline mempty #-}++data BI s = BI !Int !(Writer s)++instance Semigroup (BI s) where+ BI len0 w0 <> BI len1 w1 = BI (len0 + len1) (w0 <> w1)+ {-# inline (<>) #-}++instance Monoid (BI s) where+ mempty = BI 0 mempty+ {-# inline mempty #-}++-- | A 'Builder' for 'ByteArray's that has O(1) append.+-- To create a 'ByteArray', use 'build'. This will only+-- do one allocation.+newtype Builder = Builder (forall s. BI s)++instance Semigroup Builder where+ Builder b0 <> Builder b1 = Builder (b0 <> b1)+ {-# inline (<>) #-}++instance Monoid Builder where+ mempty = Builder mempty+ {-# inline mempty #-}++runWriter# :: Int# -> Writer s -> State# s -> (# State# s, ByteArray# #)+runWriter# sz# (W g) = \s0# -> case newByteArray# sz# s0# of+ (# s1#, marr# #) -> case g marr# 0# s1# of+ (# s2#, _ #) -> case unsafeFreezeByteArray# marr# s2# of+ (# s3#, b# #) -> (# s3#, b# #)+{-# inline runWriter# #-}++-- | Convert a 'Builder' into a 'ByteArray'.+build :: Builder -> ByteArray+build (Builder (BI (I# len#) w)) = case runRW# (runWriter# len# w) of+ (# _, b# #) -> ByteArray b#+{-# inline build #-}++writeUnaligned :: (Prim a, PrimUnaligned a)+ => a+ -> Writer s+writeUnaligned a = W $ \marr# ix0# s0# ->+ case writeUnalignedByteArray# marr# ix0# a s0# of+ s1# -> (# s1#, ix0# +# alignment# a #)+{-# inline writeUnaligned #-}++writeByteArray :: ()+ => ByteArray+ -> Int+ -> Int+ -> Writer s+writeByteArray (ByteArray src#) (I# off#) (I# len#)+ = W $ \marr# ix0# s0# ->+ case copyByteArray# src# off# marr# ix0# len# s0# of+ s1# -> (# s1#, ix0# +# len# #)+{-# inline writeByteArray #-}++-- | A 'Builder' for any 'Prim' and 'PrimUnaligned' value.+buildUnaligned :: (Prim a, PrimUnaligned a)+ => a+ -> Builder+buildUnaligned a = Builder (BI (sizeOf a) (writeUnaligned a))+{-# inline buildUnaligned #-}++-- | A 'Builder' for 'Word8'.+buildWord8 :: Word8 -> Builder+buildWord8 = buildUnaligned+{-# inline buildWord8 #-}++-- | A 'Builder' for 'Word16'.+buildWord16 :: Word16 -> Builder+buildWord16 = buildUnaligned+{-# inline buildWord16 #-}++-- | A 'Builder' for 'Word32'.+buildWord32 :: Word32 -> Builder+buildWord32 = buildUnaligned+{-# inline buildWord32 #-}++-- | A 'Builder' for 'Word64'.+buildWord64 :: Word64 -> Builder+buildWord64 = buildUnaligned+{-# inline buildWord64 #-}++-- | A 'Builder' for 'Word'.+buildWord :: Word -> Builder+buildWord = buildUnaligned+{-# inline buildWord #-}++-- | A 'Builder' for 'Int8'.+buildInt8 :: Int8 -> Builder+buildInt8 = buildUnaligned+{-# inline buildInt8 #-}++-- | A 'Builder' for 'Int16'.+buildInt16 :: Int16 -> Builder+buildInt16 = buildUnaligned+{-# inline buildInt16 #-}++-- | A 'Builder' for 'Int32'.+buildInt32 :: Int32 -> Builder+buildInt32 = buildUnaligned+{-# inline buildInt32 #-}++-- | A 'Builder' for 'Int64'.+buildInt64 :: Int64 -> Builder+buildInt64 = buildUnaligned+{-# inline buildInt64 #-}++-- | A 'Builder' for 'Int'.+buildInt :: Int -> Builder+buildInt = buildUnaligned+{-# inline buildInt #-}++-- | A 'Builder' for 'Char'.+buildChar :: Char -> Builder+buildChar = buildUnaligned+{-# inline buildChar #-}++-- | A 'Builder' for a 'ByteArray' slice.+buildByteArray :: ()+ => ByteArray -- ^ source array+ -> Int -- ^ offset into source array+ -> Int -- ^ number of bytes to copy+ -> Builder+buildByteArray b o n = Builder (BI n (writeByteArray b o n))+{-# inline buildByteArray #-}++-- | A 'Builder' for 'Float'.+buildFloat :: Float -> Builder+buildFloat = buildUnaligned+{-# inline buildFloat #-}++-- | A 'Builder' for 'Double'.+buildDouble :: Double -> Builder+buildDouble = buildUnaligned+{-# inline buildDouble #-}++-- | A 'Builder' for @'Ptr' a@.+buildPtr :: Ptr a -> Builder+buildPtr = buildUnaligned+{-# inline buildPtr #-}++-- | A 'Builder' for @'Fixed' b a@+-- This provides better control over endianness when writing.+buildFixed :: (FixedOrdering b, Bytes a, Prim a, PrimUnaligned a)+ => Fixed b a+ -> Builder+buildFixed = buildUnaligned+{-# inline buildFixed #-}