Skip to content

Commit

Permalink
Manage connection string using type converter (#3)
Browse files Browse the repository at this point in the history
* Refactor connection string type as a converter
* Add default connection string
* Avoid inserting prefix in converter round-trip
* Add missing protocols
* Rename converter properties
* Simplify default connection string
  • Loading branch information
glopesdev authored Dec 19, 2022
1 parent 19d1108 commit 2b8105e
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 353 deletions.
78 changes: 0 additions & 78 deletions src/Bonsai.ZeroMQ/ConnectionId.cs

This file was deleted.

99 changes: 0 additions & 99 deletions src/Bonsai.ZeroMQ/ConnectionIdConverter.cs

This file was deleted.

188 changes: 188 additions & 0 deletions src/Bonsai.ZeroMQ/ConnectionStringConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
using System;
using System.Collections;
using System.ComponentModel;

namespace Bonsai.ZeroMQ
{
internal class ConnectionStringConverter : StringConverter
{
const char BindPrefix = '@';
const char ConnectPrefix = '>';
const string ProtocolDelimiter = "://";

static char? GetDefaultAction(object value)
{
if (value is string connectionString && connectionString.Length > 0)
{
return connectionString[0];
}

return null;
}

static string GetProtocol(object value)
{
if (value is string connectionString)
{
var trimString = connectionString.Trim(BindPrefix, ConnectPrefix);
var separatorIndex = trimString.IndexOf(ProtocolDelimiter);
if (separatorIndex >= 0)
{
return trimString.Substring(0, separatorIndex);
}
}

return string.Empty;
}

static string GetAddress(object value)
{
if (value is string connectionString)
{
var separatorIndex = connectionString.IndexOf(ProtocolDelimiter);
return separatorIndex >= 0
? connectionString.Substring(separatorIndex + ProtocolDelimiter.Length)
: connectionString;
}

return string.Empty;
}

static char? GetActionString(Action? value)
{
return value switch
{
Action.Connect => ConnectPrefix,
Action.Bind => BindPrefix,
_ => null
};
}

static string GetProtocolString(Protocol value)
{
return value switch
{
Protocol.InProc => "inproc",
Protocol.Tcp => "tcp",
Protocol.Ipc => "ipc",
Protocol.Pgm => "pgm",
Protocol.Epgm => "epgm",
_ => string.Empty
};
}

public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
var action = (Action?)propertyValues[nameof(Action)];
var protocol = (Protocol)propertyValues[nameof(Protocol)];
var address = propertyValues["Address"];
return $"{GetActionString(action)}{GetProtocolString(protocol)}{ProtocolDelimiter}{address}";
}

public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}

public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return new PropertyDescriptorCollection(new PropertyDescriptor[]
{
new ActionDescriptor(),
new ProtocolDescriptor(),
new AddressDescriptor()
}).Sort(new[] { nameof(Action), nameof(Protocol) });
}

class ActionDescriptor : SimplePropertyDescriptor
{
public ActionDescriptor()
: base(typeof(string), nameof(Action), typeof(Action?))
{
}

public override Type PropertyType => typeof(string);

public override TypeConverter Converter => TypeDescriptor.GetConverter(typeof(Action?));

public override object GetValue(object component)
{
return GetDefaultAction(component) switch
{
BindPrefix => Action.Bind,
ConnectPrefix => Action.Connect,
_ => null
};
}

public override void SetValue(object component, object value)
{
}
}

class ProtocolDescriptor : SimplePropertyDescriptor
{

public ProtocolDescriptor()
: base(typeof(string), nameof(Protocol), typeof(Protocol))
{
}

public override TypeConverter Converter => TypeDescriptor.GetConverter(typeof(Protocol));

public override object GetValue(object component)
{
return GetProtocol(component) switch
{
"inproc" => Protocol.InProc,
"tcp" => Protocol.Tcp,
"ipc" => Protocol.Ipc,
"pgm" => Protocol.Pgm,
"epgm" => Protocol.Epgm,
_ => throw new ArgumentException("Invalid protocol type string"),
};
}

public override void SetValue(object component, object value)
{
}
}

class AddressDescriptor : SimplePropertyDescriptor
{
public AddressDescriptor()
: base(typeof(string), "Address", typeof(string))
{
}

public override object GetValue(object component)
{
return GetAddress(component);
}

public override void SetValue(object component, object value)
{
}
}

internal enum Action
{
Connect,
Bind
}

internal enum Protocol
{
InProc,
Tcp,
Ipc,
Pgm,
Epgm
}
}
}
7 changes: 7 additions & 0 deletions src/Bonsai.ZeroMQ/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Bonsai.ZeroMQ
{
internal static class Constants
{
internal const string DefaultConnectionString = "tcp://localhost:5557";
}
}
8 changes: 4 additions & 4 deletions src/Bonsai.ZeroMQ/Dealer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ namespace Bonsai.ZeroMQ
public class Dealer : Source<ZeroMQMessage>
{
/// <summary>
/// Gets or sets a value specifying the <see cref="ZeroMQ.ConnectionId"/> of the <see cref="Dealer"/> socket.
/// Gets or sets a value specifying the connection string of the <see cref="Dealer"/> socket.
/// </summary>
[TypeConverter(typeof(ConnectionIdConverter))]
public ConnectionId ConnectionId { get; set; } = new ConnectionId(SocketSettings.SocketConnection.Connect, SocketSettings.SocketProtocol.TCP, "localhost", "5557");
[TypeConverter(typeof(ConnectionStringConverter))]
public string ConnectionString { get; set; } = Constants.DefaultConnectionString;

/// <summary>
/// If no <see cref="Message"/> sequence is provided as source, creates a Dealer socket that acts only as a server listener.
Expand All @@ -43,7 +43,7 @@ public IObservable<ZeroMQMessage> Generate(IObservable<Message> message)
{
return Observable.Create<ZeroMQMessage>((observer, cancellationToken) =>
{
var dealer = new DealerSocket(ConnectionId.ToString());
var dealer = new DealerSocket(ConnectionString);
cancellationToken.Register(() => { dealer.Dispose(); });

if (message != null)
Expand Down
Loading

0 comments on commit 2b8105e

Please # to comment.