187 lines
5.8 KiB
Plaintext
187 lines
5.8 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: PacketFragment.sg
|
|
//
|
|
|
|
namespace Microsoft.Singularity.Io.Net
|
|
{
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using Microsoft.Contracts;
|
|
using Microsoft.SingSharp;
|
|
using Microsoft.Singularity;
|
|
using Microsoft.Singularity.Channels;
|
|
|
|
public rep struct PacketFragment : ITracked
|
|
{
|
|
byte [] in ExHeap data;
|
|
int start; // start position of live data in fragment
|
|
int length; // end position of live data in fragment
|
|
|
|
public void Set(byte[]! buffer, int bufferStart, int bufferBytes)
|
|
requires bufferStart + bufferBytes <= buffer.Length;
|
|
requires bufferStart >= 0;
|
|
requires bufferBytes > 0;
|
|
{
|
|
expose (this) {
|
|
if (this.data == null || this.data.Length < bufferBytes) {
|
|
delete this.data;
|
|
this.data = new [ExHeap] byte [bufferBytes];
|
|
}
|
|
this.start = 0;
|
|
this.length = bufferBytes;
|
|
Bitter.FromByteArray(this.data, 0, bufferBytes,
|
|
buffer, bufferStart);
|
|
}
|
|
}
|
|
|
|
public void Set([Claims] byte[]! in ExHeap buffer,
|
|
int bufferStart,
|
|
int bufferLength)
|
|
requires bufferStart + bufferLength <= buffer.Length;
|
|
requires bufferStart >= 0;
|
|
requires bufferLength >= 0;
|
|
{
|
|
expose (this) {
|
|
if (this.data == null || bufferLength >= this.data.Length) {
|
|
delete this.data;
|
|
this.data = buffer;
|
|
this.start = bufferStart;
|
|
this.length = bufferLength;
|
|
}
|
|
else {
|
|
Bitter.Copy(this.data, 0, bufferLength,
|
|
buffer, bufferStart);
|
|
this.start = 0;
|
|
this.length = bufferLength;
|
|
delete buffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Set(IoMemory! region, UIntPtr offset, UIntPtr length)
|
|
{
|
|
expose (this) {
|
|
this.start = 0;
|
|
this.length = (int)length.ToUInt32();
|
|
assert this.length <= this.Capacity;
|
|
Bitter.FromIoMemory(this.data, this.start, this.length,
|
|
region, (int)offset.ToUInt32());
|
|
}
|
|
}
|
|
|
|
public int Length
|
|
{
|
|
get { expose (this) { return this.length; } }
|
|
set {
|
|
expose (this) {
|
|
assert value <= this.Capacity;
|
|
this.length = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// [Pure]
|
|
public int Capacity
|
|
{
|
|
get {
|
|
expose (this) {
|
|
return this.data == null ? 0 : this.data.Length;
|
|
}
|
|
}
|
|
}
|
|
|
|
// [Pure]
|
|
internal int Start
|
|
{
|
|
get { expose (this) { return this.start; } }
|
|
}
|
|
|
|
// [Pure]
|
|
public bool HasData
|
|
{
|
|
get { expose (this) { return this.data != null; } }
|
|
}
|
|
|
|
public void TrimHead(int bytesToTrim)
|
|
requires bytesToTrim <= this.Length;
|
|
ensures Length == old(Length) - bytesToTrim;
|
|
ensures this.Start == old(this.Start) + bytesToTrim;
|
|
{
|
|
expose (this) {
|
|
this.start += bytesToTrim;
|
|
this.length -= bytesToTrim;
|
|
}
|
|
}
|
|
|
|
public void TrimTail(int bytesToTrim)
|
|
requires bytesToTrim <= this.Length;
|
|
ensures Length == old(Length) - bytesToTrim;
|
|
{
|
|
expose (this) {
|
|
this.length -= bytesToTrim;
|
|
}
|
|
}
|
|
|
|
public void Untrim()
|
|
{
|
|
expose (this) {
|
|
this.start = 0;
|
|
this.length = this.Capacity;
|
|
}
|
|
}
|
|
|
|
[Pure]
|
|
public void GetFragmentRange(out UIntPtr virtualAddr,
|
|
out int lengthBytes)
|
|
{
|
|
expose (this) {
|
|
if (this.data != null) {
|
|
virtualAddr = Bitter.ToAddress(this.data, this.start);
|
|
lengthBytes = this.length;
|
|
}
|
|
else {
|
|
virtualAddr = UIntPtr.Zero;
|
|
lengthBytes = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Copy(byte[]! destination, int offset)
|
|
requires offset >= 0 && offset < destination.Length;
|
|
requires destination.Length - offset >= this.Length;
|
|
{
|
|
expose (this) {
|
|
if (this.data != null) {
|
|
Bitter.ToByteArray(this.data, this.start, this.length,
|
|
destination, offset);
|
|
return this.length;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Append(byte value)
|
|
requires this.Start + this.Length < this.Capacity;
|
|
{
|
|
expose (this) {
|
|
assert this.data != null;
|
|
this.data[this.start + this.length] = value;
|
|
this.length++;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
delete this.data;
|
|
this.data = null;
|
|
}
|
|
}
|
|
}
|