Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
CypherPotato committed Jul 6, 2024
1 parent 12885e1 commit cbf7009
Show file tree
Hide file tree
Showing 35 changed files with 401 additions and 342 deletions.
20 changes: 16 additions & 4 deletions src/Ext/CircularBuffer.cs → src/Entity/CircularBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ namespace Sisk.Core.Entity;
/// </summary>
/// <typeparam name="T">The type of elements stored in the buffer.</typeparam>
/// <exclude/>
public class CircularBuffer<T> : IEnumerable<T>
public class CircularBuffer<T> : IEnumerable<T>, IReadOnlyList<T>
{
T[] items;
private T[] items;

int capacity = 0;
int capacity = 0,
addedItems = 0;

/// <summary>
/// Creates an new instance of the <see cref="CircularBuffer{T}"/> with the specified
Expand All @@ -29,6 +30,7 @@ public class CircularBuffer<T> : IEnumerable<T>
/// <param name="capacity">The circular buffer capacity.</param>
public CircularBuffer(int capacity)
{
if (capacity <= 0) throw new ArgumentOutOfRangeException("Capacity cannot be less or equals to zero.");
this.capacity = capacity;
items = new T[capacity];
}
Expand All @@ -47,6 +49,7 @@ public void Add(T item)
items[i] = items[i - 1];
}

addedItems = Math.Min(Capacity, addedItems + 1);
items[0] = item;
}
}
Expand All @@ -57,6 +60,7 @@ public void Add(T item)
public void Clear()
{
items = new T[capacity];
addedItems = 0;
}

/// <summary>
Expand All @@ -65,7 +69,7 @@ public void Clear()
/// <param name="capacity">The new size for this circular buffer.</param>
public void Resize(int capacity)
{
if (capacity <= 0) throw new ArgumentException("Capacity cannot be less or equals to zero.");
if (capacity <= 0) throw new ArgumentOutOfRangeException("Capacity cannot be less or equals to zero.");
Array.Resize(ref items, capacity);
this.capacity = capacity;
}
Expand All @@ -86,6 +90,14 @@ public void Resize(int capacity)
/// </summary>
public int Capacity { get => capacity; }

/// <summary>
/// Gets the amount of added items in this circular buffer.
/// </summary>
public int Count => addedItems;

/// <inheritdoc/>
public T this[int index] => items[index];

/// <inheritdoc/>
/// <exclude/>
public IEnumerator<T> GetEnumerator()
Expand Down
2 changes: 1 addition & 1 deletion src/Entity/MultipartFormCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Sisk.Core.Entity;
/// <summary>
/// Represents an class which hosts an multipart form data contents.
/// </summary>
public class MultipartFormCollection : IEnumerable<MultipartObject>, IReadOnlyList<MultipartObject>, IReadOnlyCollection<MultipartObject>
public sealed class MultipartFormCollection : IEnumerable<MultipartObject>, IReadOnlyList<MultipartObject>, IReadOnlyCollection<MultipartObject>
{
private readonly IList<MultipartObject> _items;

Expand Down
91 changes: 53 additions & 38 deletions src/Entity/MultipartObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// Repository: https://github.com/sisk-http/core

using Sisk.Core.Http;
using Sisk.Core.Internal;
using System.Collections.Specialized;
using System.Text;

Expand All @@ -16,7 +17,7 @@ namespace Sisk.Core.Entity
/// <summary>
/// Represents an multipart/form-data object.
/// </summary>
public class MultipartObject
public sealed class MultipartObject
{
private readonly Encoding _baseEncoding;

Expand Down Expand Up @@ -56,7 +57,7 @@ public class MultipartObject
}

/// <summary>
/// Reads the content bytes using the Http request content-encoding.
/// Reads the content bytes using the HTTP request content-encoding.
/// </summary>
public string? ReadContentAsString()
{
Expand All @@ -68,46 +69,57 @@ public class MultipartObject
/// </summary>
public MultipartObjectCommonFormat GetCommonFileFormat()
{
IEnumerable<byte> len8 = ContentBytes.Take(8);
IEnumerable<byte> len4 = ContentBytes.Take(4);
IEnumerable<byte> len3 = ContentBytes.Take(3);
int byteLen = ContentBytes.Length;

if (len8.SequenceEqual(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }))
if (byteLen >= 8)
{
return MultipartObjectCommonFormat.PNG;
}
else if (len4.SequenceEqual(new byte[] { (byte)'R', (byte)'I', (byte)'F', (byte)'F' }))
{
return MultipartObjectCommonFormat.WEBP;
}
else if (len4.SequenceEqual(new byte[] { 0x25, 0x50, 0x44, 0x46 }))
{
return MultipartObjectCommonFormat.PDF;
}
else if (len3.SequenceEqual(new byte[] { 0xFF, 0xD8, 0xFF }))
{
return MultipartObjectCommonFormat.JPEG;
}
else if (len3.SequenceEqual(new byte[] { 73, 73, 42 }))
{
return MultipartObjectCommonFormat.TIFF;
}
else if (len3.SequenceEqual(new byte[] { 77, 77, 42 }))
{
return MultipartObjectCommonFormat.TIFF;
}
else if (len3.SequenceEqual(new byte[] { 0x42, 0x4D }))
{
return MultipartObjectCommonFormat.BMP;
}
else if (len3.SequenceEqual(new byte[] { 0x47, 0x46, 0x49 }))
Span<byte> len8 = ContentBytes.AsSpan(0, 8);

if (len8.SequenceEqual(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }))
{
return MultipartObjectCommonFormat.PNG;
}
}
if (byteLen >= 4)
{
return MultipartObjectCommonFormat.GIF;
Span<byte> len4 = ContentBytes.AsSpan(0, 4);

if (len4.SequenceEqual(new byte[] { (byte)'R', (byte)'I', (byte)'F', (byte)'F' }))
{
return MultipartObjectCommonFormat.WEBP;
}
else if (len4.SequenceEqual(new byte[] { 0x25, 0x50, 0x44, 0x46 }))
{
return MultipartObjectCommonFormat.PDF;
}
}
else
if (byteLen >= 3)
{
return MultipartObjectCommonFormat.Unknown;
Span<byte> len3 = ContentBytes.AsSpan(0, 3);

if (len3.SequenceEqual(new byte[] { 0xFF, 0xD8, 0xFF }))
{
return MultipartObjectCommonFormat.JPEG;
}
else if (len3.SequenceEqual(new byte[] { 73, 73, 42 }))
{
return MultipartObjectCommonFormat.TIFF;
}
else if (len3.SequenceEqual(new byte[] { 77, 77, 42 }))
{
return MultipartObjectCommonFormat.TIFF;
}
else if (len3.SequenceEqual(new byte[] { 0x42, 0x4D }))
{
return MultipartObjectCommonFormat.BMP;
}
else if (len3.SequenceEqual(new byte[] { 0x47, 0x46, 0x49 }))
{
return MultipartObjectCommonFormat.GIF;
}
}

return MultipartObjectCommonFormat.Unknown;
}

internal MultipartObject(NameValueCollection headers, string? filename, string name, byte[]? body, Encoding encoding)
Expand All @@ -120,9 +132,12 @@ internal MultipartObject(NameValueCollection headers, string? filename, string n
_baseEncoding = encoding;
}

//
// we should rewrite it using Spans<>, but there are so many code and it would take
// days...
internal static MultipartFormCollection ParseMultipartObjects(HttpRequest req)
{
string? contentType = req.Headers["Content-Type"];
string? contentType = req.Headers[HttpKnownHeaderNames.ContentType];
if (contentType is null)
{
throw new InvalidOperationException(SR.MultipartObject_ContentTypeMissing);
Expand Down Expand Up @@ -252,7 +267,7 @@ bool Equals(byte[] source, byte[] separator, int index)
}

// parse field name
string[] val = headers["Content-Disposition"]?.Split(';') ?? Array.Empty<string>();
string[] val = headers[HttpKnownHeaderNames.ContentDisposition]?.Split(';') ?? Array.Empty<string>();
string? fieldName = null;
string? fieldFilename = null;

Expand Down
6 changes: 3 additions & 3 deletions src/Entity/StringValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
namespace Sisk.Core.Entity;

/// <summary>
/// Represents an instance that hosts a string value and allows conversion to common types.
/// Represents an option/monad item that wraps an string value and allows conversion to most common types.
/// </summary>
public struct StringValue : ICloneable, IEquatable<StringValue>, IComparable<StringValue>
public readonly struct StringValue : ICloneable, IEquatable<StringValue>, IComparable<StringValue>
{
private readonly string? _ref;
private readonly string argName;
Expand All @@ -33,7 +33,7 @@ internal StringValue(string name, string type, string? data)
public string Name { get => argName; }

/// <summary>
/// Gets the value slot of this <see cref="StringValue"/>.
/// Gets the value of the current <see cref="StringValue"/> string if it has been assigned a valid underlying value.
/// </summary>
public string? Value { get => _ref; }

Expand Down
18 changes: 9 additions & 9 deletions src/Http/Handlers/HttpServerHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,36 @@ public abstract class HttpServerHandler
/// <summary>
/// Method that is called immediately before starting the <see cref="HttpServer"/>.
/// </summary>
/// <param name="server">The Http server entity which is starting.</param>
/// <param name="server">The HTTP server entity which is starting.</param>
protected virtual void OnServerStarting(HttpServer server) { }
internal void InvokeOnServerStarting(HttpServer server) => OnServerStarting(server);

/// <summary>
/// Method that is called immediately after starting the <see cref="HttpServer"/>, when it's
/// ready and listening.
/// </summary>
/// <param name="server">The Http server entity which is ready.</param>
/// <param name="server">The HTTP server entity which is ready.</param>
protected virtual void OnServerStarted(HttpServer server) { }
internal void InvokeOnServerStarted(HttpServer server) => OnServerStarted(server);

/// <summary>
/// Method that is called before the <see cref="HttpServer"/> stop, when it is
/// stopping from listening requests.
/// </summary>
/// <param name="server">The Http server entity which is stopping.</param>
/// <param name="server">The HTTP server entity which is stopping.</param>
protected virtual void OnServerStopping(HttpServer server) { }
internal void InvokeOnServerStopping(HttpServer server) => OnServerStopping(server);

/// <summary>
/// Method that is called after the <see cref="HttpServer"/> is stopped, meaning
/// it has stopped from listening to requests.
/// </summary>
/// <param name="server">The Http server entity which has stopped.</param>
/// <param name="server">The HTTP server entity which has stopped.</param>
protected virtual void OnServerStopped(HttpServer server) { }
internal void InvokeOnServerStopped(HttpServer server) => OnServerStopped(server);

/// <summary>
/// Method that is called when an <see cref="Router"/> is binded to the Http server.
/// Method that is called when an <see cref="Router"/> is binded to the HTTP server.
/// </summary>
/// <param name="router">The router entity which is binded.</param>
protected virtual void OnSetupRouter(Router router) { }
Expand All @@ -65,22 +65,22 @@ protected virtual void OnContextBagCreated(HttpContextBagRepository contextBag)

/// <summary>
/// Method that is called when an <see cref="HttpRequest"/> is received in the
/// Http server.
/// HTTP server.
/// </summary>
/// <param name="request">The connecting Http request entity.</param>
/// <param name="request">The connecting HTTP request entity.</param>
protected virtual void OnHttpRequestOpen(HttpRequest request) { }
internal void InvokeOnHttpRequestOpen(HttpRequest request) => OnHttpRequestOpen(request);

/// <summary>
/// Method that is called when an <see cref="HttpRequest"/> is closed in the
/// Http server.
/// HTTP server.
/// </summary>
/// <param name="result">The result of the execution of the request.</param>
protected virtual void OnHttpRequestClose(HttpServerExecutionResult result) { }
internal void InvokeOnHttpRequestClose(HttpServerExecutionResult result) => OnHttpRequestClose(result);

/// <summary>
/// Method that is called when an exception is caught in the Http server. This method is called
/// Method that is called when an exception is caught in the HTTP server. This method is called
/// regardless of whether <see cref="HttpServerConfiguration.ThrowExceptions"/> is enabled or not.
/// </summary>
/// <param name="exception">The exception object.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
// File name: ConfigurationContext.cs
// Repository: https://github.com/sisk-http/core

using Sisk.Core.Http;
using Sisk.Core.Http.Hosting;

namespace Sisk.Core.Internal.ServiceProvider;
namespace Sisk.Core.Http.Hosting;

/// <summary>
/// Represents a reading context for a portable configuration file.
Expand Down
8 changes: 4 additions & 4 deletions src/Http/Hosting/HttpServerHostContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ namespace Sisk.Core.Http.Hosting;
/// <summary>
/// Represents the class that hosts most of the components needed to run a Sisk application.
/// </summary>
public class HttpServerHostContext : IDisposable
public sealed class HttpServerHostContext : IDisposable
{
/// <summary>
/// Gets the initialization parameters from the portable configuration file.
/// </summary>
public InitializationParameterCollection Parameters { get; } = new InitializationParameterCollection();

/// <summary>
/// Gets the host Http server.
/// Gets the host HTTP server.
/// </summary>
public HttpServer HttpServer { get; private set; }

Expand Down Expand Up @@ -66,7 +66,7 @@ internal HttpServerHostContext(HttpServer httpServer)
}

/// <summary>
/// Starts the Http server.
/// Starts the HTTP server.
/// </summary>
/// <param name="preventHault">Optional. Specifies if the application should pause the main application loop.</param>
/// <param name="verbose">Optional. Specifies if the application should write the listening prefix welcome message.</param>
Expand All @@ -86,7 +86,7 @@ public void Start(bool verbose = true, bool preventHault = true)
}

/// <summary>
/// Asynchronously starts the Http server.
/// Asynchronously starts the HTTP server.
/// </summary>
/// <param name="preventHault">Optional. Specifies if the application should pause the main application loop.</param>
/// <param name="verbose">Optional. Specifies if the application should write the listening prefix welcome message.</param>
Expand Down
6 changes: 3 additions & 3 deletions src/Http/Hosting/HttpServerHostContextBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ public HttpServerHostContext Build()
}

/// <summary>
/// Defines a function that will be executed immediately before starting the Http server.
/// Defines a function that will be executed immediately before starting the HTTP server.
/// </summary>
/// <param name="bootstrapAction">The action which will be executed before the Http server start.</param>
/// <param name="bootstrapAction">The action which will be executed before the HTTP server start.</param>
public HttpServerHostContextBuilder UseBootstraper(Action bootstrapAction)
{
_context.HttpServer.handler._default._serverBootstraping = bootstrapAction;
Expand Down Expand Up @@ -134,7 +134,7 @@ public HttpServerHostContextBuilder UseListeningPort(string uri)
/// <summary>
/// Sets the main <see cref="ListeningPort"/> of this host builder.
/// </summary>
/// <param name="listeningPort">The <see cref="ListeningPort"/> object which the Http server will listen to.</param>
/// <param name="listeningPort">The <see cref="ListeningPort"/> object which the HTTP server will listen to.</param>
public HttpServerHostContextBuilder UseListeningPort(ListeningPort listeningPort)
{
_context.ServerConfiguration.ListeningHosts[0].Ports[0] = listeningPort;
Expand Down
2 changes: 0 additions & 2 deletions src/Http/Hosting/IConfigurationReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
// File name: IConfigurationReader.cs
// Repository: https://github.com/sisk-http/core

using Sisk.Core.Internal.ServiceProvider;

namespace Sisk.Core.Http.Hosting;

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Hosting/InitializationParameterCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Sisk.Core.Http.Hosting;
/// <summary>
/// Provides a collection of HTTP server initialization variables.
/// </summary>
public class InitializationParameterCollection : IDictionary<string, string?>
public sealed class InitializationParameterCollection : IDictionary<string, string?>
{
private readonly NameValueCollection _decorator = new NameValueCollection();
private bool _isReadonly = false;
Expand Down
Loading

0 comments on commit cbf7009

Please sign in to comment.