4 people like it.
Like the snippet!
ByteString
An initial attempt at creating a ByteString type based on the Haskell version.
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