4 people like it.

ByteString

An initial attempt at creating a ByteString type based on the Haskell version.

ByteString

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
open System
open System.Diagnostics

/// ByteString is a functional ArraySegment<byte> that also implements IEnumerable<byte>.
/// NOTE: This type should really be moved into a set of extension types missing from F#.
type ByteString = BS of byte array * int * int
  with
  interface System.Collections.Generic.IEnumerable<byte> with
    member this.GetEnumerator() =
      let (BS(a,o,l)) = this
      let inner = seq { for i in o..l do yield a.[i] }
      inner.GetEnumerator()
    member this.GetEnumerator() =
      let (BS(a,o,l)) = this
      let inner = seq { for i in o..l do yield a.[i] }
      inner.GetEnumerator() :> System.Collections.IEnumerator

  static member op_Equality (BS(x,o,l), BS(x',o',l')) =
    if not (l = l') then false
    else (l = 0 && l' = 0) || (x = x' && o = o') // TODO: Add byte by byte comparison

  /// Implements the [] operator, which is not available on anything but the List<_> type.
  static member op_Nil = BS(Array.empty,0,0)

  /// Implements the :: operator, which is not available on anything but the List<_> type.
  /// op_Cons uses Buffer.SetByte and Buffer.BlockCopy for efficient array operations.
  /// Please note that a new array is created and both the head and tail are copied in,
  /// disregarding any additional bytes in the original tail array.
  static member op_Cons (hd, BS(x,o,l)) =
    if l = 0 then ByteString.singleton hd
    else let buffer = Array.zeroCreate<byte> (l + 1)
         Buffer.SetByte(buffer,0,hd)
         Buffer.BlockCopy(x,o,buffer,1,l)
         BS(buffer,0,l+1)

  /// Implements the @ operator, which is not available on anything but the List<_> type.
  /// op_Append uses Buffer.BlockCopy for efficient array operations.
  /// Please note that a new array is created and both arrays are copied in,
  /// disregarding any additional bytes in the original, underlying arrays.
  static member op_Append (a, b) =
    if ByteString.isEmpty a then b
    elif ByteString.isEmpty b then a
    else let (BS(x,o,l)) = a
         let (BS(x',o',l')) = b
         let buffer = Array.zeroCreate<byte> (l + l')
         Buffer.BlockCopy(x,o,buffer,0,l)
         Buffer.BlockCopy(x',o',buffer,l,l')
         BS(buffer,0,l+l')

  static member empty = ByteString.op_Nil
  static member singleton c = BS(Array.create 1 c, 0, 1)
  static member create bs = BS(bs, 0, bs.Length)
  static member ofSegment (segment:ArraySegment<byte>) = BS(segment.Array, segment.Offset, segment.Count)
  static member ofSeq s = let arr = Array.ofSeq s in BS(arr, 0, arr.Length)
  static member ofList l = BS(Array.ofList l, 0, l.Length)
  static member ofString (s:string) = s.ToCharArray() |> Array.map byte |> ByteString.create
  static member toList (BS(x,o,l)) = let len = l-1 in [ for i in o..len -> x.[i] ]
  static member toString (BS(x,o,l)) = let len = l-1 in System.Text.Encoding.ASCII.GetString(x,o,l)
  static member isEmpty (BS(_,_,l)) = Debug.Assert(l >= 0); l <= 0
  static member length (BS(_,_,l)) = Debug.Assert(l >= 0); l
  static member head (BS(x,o,l)) = if l <= 0 then failwith "" else x.[o]
  static member tail (BS(x,o,l)) = BS(x,o+1,l-1)
  static member cons hd tl = ByteString.op_Cons(hd, tl)
  static member append a b = ByteString.op_Append(a, b)
  static member take n (BS(x,o,l)) = Debug.Assert(l >= n); BS(x,o,n)
  
  static member split pred bs =
    // List-style
//    let rec loop l acc =
//      if ByteString.isEmpty l then (ByteString.take acc bs, ByteString.empty)
//      else
//        let hd, tl = ByteString.head l, ByteString.tail l
//        if ByteString.isEmpty tl && not (pred hd) then (ByteString.take acc bs, ByteString.empty)
//        elif pred hd then (ByteString.take acc bs, l)
//        else loop tl (acc+1)
//    loop bs 0
    let (BS(x,o,l)) = bs
    let rec loop acc =
      if l-acc = 0 then (BS(x,o,acc), ByteString.empty)
      else
        if l-(acc+1) = 0 && not (pred x.[o+acc]) then (BS(x,o,acc), ByteString.empty)
        elif pred x.[o+acc] then (BS(x,o,acc), BS(x,o+acc,l-acc))
        else loop (acc+1)
    loop 0

  static member splitAt n bs =
    let pred i = i >= n
    // List-style
//    let rec loop l acc =
//      if ByteString.isEmpty l then (ByteString.take acc bs, ByteString.empty)
//      else
//        let hd, tl = ByteString.head l, ByteString.tail l
//        if ByteString.isEmpty tl && not (pred acc) then (ByteString.take acc bs, ByteString.empty)
//        elif pred acc then (ByteString.take acc bs, l)
//        else loop tl (acc+1)
//    loop bs 0
    let (BS(x,o,l)) = bs
    let rec loop acc =
      if l-acc = 0 then (BS(x,o,acc), ByteString.empty)
      else
        if l-(acc+1) = 0 && not (pred acc) then (BS(x,o,acc), ByteString.empty)
        elif pred acc then (BS(x,o,acc), BS(x,o+acc,l-acc))
        else loop (acc+1)
    loop 0
namespace System
namespace System.Diagnostics
type ByteString =
  | BS of byte array * int * int
  interface IEnumerable<byte>
  static member append : a:ByteString -> b:ByteString -> ByteString
  static member cons : hd:byte -> tl:ByteString -> ByteString
  static member create : bs:byte array -> ByteString
  static member empty : ByteString
  static member ( [] ) : ByteString
  static member head : ByteString -> byte
  static member isEmpty : ByteString -> bool
  static member length : ByteString -> int
  static member ofList : l:byte list -> ByteString
  static member ofSegment : segment:ArraySegment<byte> -> ByteString
  static member ofSeq : s:seq<byte> -> ByteString
  static member ofString : s:string -> ByteString
  static member ( @ ) : a:ByteString * b:ByteString -> ByteString
  static member op_Cons : hd:byte * ByteString -> ByteString
  static member ( = ) : ByteString * ByteString -> bool
  static member singleton : c:byte -> ByteString
  static member split : pred:(byte -> bool) -> bs:ByteString -> ByteString * ByteString
  static member splitAt : n:int -> bs:ByteString -> ByteString * ByteString
  static member tail : ByteString -> ByteString
  static member take : n:int -> ByteString -> ByteString
  static member toList : ByteString -> byte list
  static member toString : ByteString -> string

Full name: FSharp.Collections.ByteString.ByteString


 ByteString is a functional ArraySegment<byte> that also implements IEnumerable<byte>.
 NOTE: This type should really be moved into a set of extension types missing from F#.
union case ByteString.BS: byte array * int * int -> ByteString
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
type 'T array = 'T []

Full name: Microsoft.FSharp.Core.array<_>
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
namespace System.Collections
namespace System.Collections.Generic
type IEnumerable<'T> =
  member GetEnumerator : unit -> IEnumerator<'T>

Full name: System.Collections.Generic.IEnumerable<_>
val this : ByteString
override ByteString.GetEnumerator : unit -> Collections.Generic.IEnumerator<byte>

Full name: FSharp.Collections.ByteString.ByteString.GetEnumerator
val a : byte array
val o : int
val l : int
val inner : seq<byte>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val i : int
Collections.Generic.IEnumerable.GetEnumerator() : Collections.Generic.IEnumerator<byte>
override ByteString.GetEnumerator : unit -> Collections.IEnumerator

Full name: FSharp.Collections.ByteString.ByteString.GetEnumerator
type IEnumerator =
  member Current : obj
  member MoveNext : unit -> bool
  member Reset : unit -> unit

Full name: System.Collections.IEnumerator
val x : byte array
val x' : byte array
val o' : int
val l' : int
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val empty<'T> : 'T []

Full name: Microsoft.FSharp.Collections.Array.empty
static member ByteString.op_Cons : hd:byte * ByteString -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.op_Cons


 Implements the :: operator, which is not available on anything but the List<_> type.
 op_Cons uses Buffer.SetByte and Buffer.BlockCopy for efficient array operations.
 Please note that a new array is created and both the head and tail are copied in,
 disregarding any additional bytes in the original tail array.
val hd : byte
static member ByteString.singleton : c:byte -> ByteString
val buffer : byte []
val zeroCreate : count:int -> 'T []

Full name: Microsoft.FSharp.Collections.Array.zeroCreate
type Buffer =
  static member BlockCopy : src:Array * srcOffset:int * dst:Array * dstOffset:int * count:int -> unit
  static member ByteLength : array:Array -> int
  static member GetByte : array:Array * index:int -> byte
  static member SetByte : array:Array * index:int * value:byte -> unit

Full name: System.Buffer
Buffer.SetByte(array: Array, index: int, value: byte) : unit
Buffer.BlockCopy(src: Array, srcOffset: int, dst: Array, dstOffset: int, count: int) : unit
val a : ByteString
val b : ByteString
static member ByteString.isEmpty : ByteString -> bool
static member ByteString.empty : ByteString

Full name: FSharp.Collections.ByteString.ByteString.empty
property ByteString.op_Nil: ByteString


 Implements the [] operator, which is not available on anything but the List<_> type.
static member ByteString.singleton : c:byte -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.singleton
val c : byte
val create : count:int -> value:'T -> 'T []

Full name: Microsoft.FSharp.Collections.Array.create
static member ByteString.create : bs:byte array -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.create
val bs : byte array
property Array.Length: int
static member ByteString.ofSegment : segment:ArraySegment<byte> -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.ofSegment
val segment : ArraySegment<byte>
Multiple items
type ArraySegment<'T> =
  struct
    new : array:'T[] -> ArraySegment<'T> + 1 overload
    member Array : 'T[]
    member Count : int
    member Equals : obj:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member Offset : int
  end

Full name: System.ArraySegment<_>

--------------------
ArraySegment()
ArraySegment(array: 'T []) : unit
ArraySegment(array: 'T [], offset: int, count: int) : unit
property ArraySegment.Array: byte []
property ArraySegment.Offset: int
property ArraySegment.Count: int
static member ByteString.ofSeq : s:seq<byte> -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.ofSeq
val s : seq<byte>
val arr : byte []
val ofSeq : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Array.ofSeq
static member ByteString.ofList : l:byte list -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.ofList
val l : byte list
val ofList : list:'T list -> 'T []

Full name: Microsoft.FSharp.Collections.Array.ofList
property List.Length: int
static member ByteString.ofString : s:string -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.ofString
val s : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
String.ToCharArray() : char []
String.ToCharArray(startIndex: int, length: int) : char []
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
static member ByteString.create : bs:byte array -> ByteString
static member ByteString.toList : ByteString -> byte list

Full name: FSharp.Collections.ByteString.ByteString.toList
val len : int
static member ByteString.toString : ByteString -> string

Full name: FSharp.Collections.ByteString.ByteString.toString
namespace System.Text
type Encoding =
  member BodyName : string
  member Clone : unit -> obj
  member CodePage : int
  member DecoderFallback : DecoderFallback with get, set
  member EncoderFallback : EncoderFallback with get, set
  member EncodingName : string
  member Equals : value:obj -> bool
  member GetByteCount : chars:char[] -> int + 3 overloads
  member GetBytes : chars:char[] -> byte[] + 5 overloads
  member GetCharCount : bytes:byte[] -> int + 2 overloads
  ...

Full name: System.Text.Encoding
property Text.Encoding.ASCII: Text.Encoding
Text.Encoding.GetString(bytes: byte []) : string
Text.Encoding.GetString(bytes: byte [], index: int, count: int) : string
static member ByteString.isEmpty : ByteString -> bool

Full name: FSharp.Collections.ByteString.ByteString.isEmpty
type Debug =
  static member Assert : condition:bool -> unit + 3 overloads
  static member AutoFlush : bool with get, set
  static member Close : unit -> unit
  static member Fail : message:string -> unit + 1 overload
  static member Flush : unit -> unit
  static member Indent : unit -> unit
  static member IndentLevel : int with get, set
  static member IndentSize : int with get, set
  static member Listeners : TraceListenerCollection
  static member Print : message:string -> unit + 1 overload
  ...

Full name: System.Diagnostics.Debug
Debug.Assert(condition: bool) : unit
Debug.Assert(condition: bool, message: string) : unit
Debug.Assert(condition: bool, message: string, detailMessage: string) : unit
Debug.Assert(condition: bool, message: string, detailMessageFormat: string, [<ParamArray>] args: obj []) : unit
static member ByteString.length : ByteString -> int

Full name: FSharp.Collections.ByteString.ByteString.length
static member ByteString.head : ByteString -> byte

Full name: FSharp.Collections.ByteString.ByteString.head
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
static member ByteString.tail : ByteString -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.tail
static member ByteString.cons : hd:byte -> tl:ByteString -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.cons
val tl : ByteString
static member ByteString.op_Cons : hd:byte * ByteString -> ByteString


 Implements the :: operator, which is not available on anything but the List<_> type.
 op_Cons uses Buffer.SetByte and Buffer.BlockCopy for efficient array operations.
 Please note that a new array is created and both the head and tail are copied in,
 disregarding any additional bytes in the original tail array.
static member ByteString.append : a:ByteString -> b:ByteString -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.append
static member ByteString.( @ ) : a:ByteString * b:ByteString -> ByteString


 Implements the @ operator, which is not available on anything but the List<_> type.
 op_Append uses Buffer.BlockCopy for efficient array operations.
 Please note that a new array is created and both arrays are copied in,
 disregarding any additional bytes in the original, underlying arrays.
static member ByteString.take : n:int -> ByteString -> ByteString

Full name: FSharp.Collections.ByteString.ByteString.take
val n : int
static member ByteString.split : pred:(byte -> bool) -> bs:ByteString -> ByteString * ByteString

Full name: FSharp.Collections.ByteString.ByteString.split
val pred : (byte -> bool)
val bs : ByteString
val loop : (int -> ByteString * ByteString)
val acc : int
property ByteString.empty: ByteString
static member ByteString.splitAt : n:int -> bs:ByteString -> ByteString * ByteString

Full name: FSharp.Collections.ByteString.ByteString.splitAt
val pred : (int -> bool)

More information

Link:http://fssnip.net/6B
Posted:12 years ago
Author:Ryan Riley
Tags: bytestring , stream , list , sequence , arraysegment