singrdk/base/Contracts/Io.Net.Contracts/PacketFragment.sg

187 lines
5.8 KiB
Plaintext
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// 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;
}
}
}