Skip to content

Commit 09d611d

Browse files
AndyPookmhowlett
authored andcommitted
rework Config ctors v2 (#979)
* rework Config ctors * fix whitespace * "smarter" config line parsing * remove unneeded Trim()s
1 parent 8bfe345 commit 09d611d

File tree

3 files changed

+124
-98
lines changed

3 files changed

+124
-98
lines changed

src/ConfigGen/Program.cs

Lines changed: 63 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ namespace ConfigGen
1212
internal class MappingConfiguration
1313
{
1414
/// <summary>
15-
/// librdkafka _RK_C_S2I properties are automatically interpreted as enums, however
16-
/// _RK_C_STR properties with discrete set of allowed values are not. Enum values for
15+
/// librdkafka _RK_C_S2I properties are automatically interpreted as enums, however
16+
/// _RK_C_STR properties with discrete set of allowed values are not. Enum values for
1717
/// these property types are specified here.
1818
/// </summary>
1919
/// <remarks>
20-
/// sasl.mechanisms is an awkward case because the values contain '-' characters (and
20+
/// sasl.mechanisms is an awkward case because the values contain '-' characters (and
2121
/// there are other values that contain the '_' character, so can't 1:1 map with this).
2222
/// This type is defined by hand later.
2323
/// </remarks>
@@ -31,7 +31,7 @@ internal class MappingConfiguration
3131
/// A function that filters out properties from the librdkafka list that should
3232
/// not be automatically extracted.
3333
/// </summary>
34-
internal static List<PropertySpecification> RemoveLegacyOrNotRelevant(List<PropertySpecification> props)
34+
internal static List<PropertySpecification> RemoveLegacyOrNotRelevant(List<PropertySpecification> props)
3535
=> props.Where(p => {
3636
// handled as a special case.
3737
if (p.Name == "sasl.mechanisms") { return false; }
@@ -204,7 +204,7 @@ public Acks? Acks
204204

205205
}
206206

207-
207+
208208
class PropertySpecification : IComparable
209209
{
210210
public PropertySpecification() {}
@@ -370,7 +370,7 @@ static string createClassFooter()
370370
static string createEnums(List<PropertySpecification> props)
371371
{
372372
var codeText = "";
373-
for (int j=0; j<props.Count(); ++j)
373+
for (int j = 0; j < props.Count(); ++j)
374374
{
375375
var prop = props[j];
376376
List<string> vs = null;
@@ -393,14 +393,14 @@ static string createEnums(List<PropertySpecification> props)
393393
codeText += $" /// </summary>\n";
394394
codeText += $" public enum {ConfigNameToDotnetName(prop.Name)}\n";
395395
codeText += $" {{\n";
396-
for (int i=0; i<vs.Count; ++i)
396+
for (int i = 0; i < vs.Count; ++i)
397397
{
398398
var v = vs[i];
399399
var nm = EnumNameToDotnetName(v);
400400
codeText += $" /// <summary>\n";
401401
codeText += $" /// {nm}\n";
402402
codeText += $" /// </summary>\n";
403-
codeText += $" {nm}{(i == vs.Count-1 ? "" : ",\n")}\n";
403+
codeText += $" {nm}{(i == vs.Count - 1 ? "" : ",\n")}\n";
404404
}
405405
codeText += $" }}\n";
406406
}
@@ -418,35 +418,45 @@ static string createClassHeader(string name, string docs, bool derive)
418418
return codeText;
419419
}
420420

421-
static string createConsumerSpecific()
421+
static string createClassConstructors(string name)
422422
{
423-
return
424-
@" /// <summary>
425-
/// Initialize a new empty <see cref=""ConsumerConfig"" /> instance.
423+
var codeText = $@"
424+
/// <summary>
425+
/// Initialize a new empty <see cref=""{name}"" /> instance.
426426
/// </summary>
427-
public ConsumerConfig() {}
427+
public {name}() : base() {{ }}
428428
429429
/// <summary>
430-
/// Initialize a new <see cref=""ConsumerConfig"" /> instance based on
430+
/// Initialize a new <see cref=""{name}"" /> instance wrapping
431431
/// an existing <see cref=""ClientConfig"" /> instance.
432+
/// This will change the values ""in-place"" i.e. operations on this class WILL modify the provided collection
432433
/// </summary>
433-
public ConsumerConfig(ClientConfig config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
434+
public {name}(ClientConfig config) : base(config) {{ }}
434435
435436
/// <summary>
436-
/// Initialize a new <see cref=""ConsumerConfig"" /> instance based on
437+
/// Initialize a new <see cref=""{name}"" /> instance wrapping
437438
/// an existing key/value pair collection.
439+
/// This will change the values ""in-place"" i.e. operations on this class WILL modify the provided collection
438440
/// </summary>
439-
public ConsumerConfig(IEnumerable<KeyValuePair<string, string>> config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
441+
public {name}(IDictionary<string, string> config) : base(config) {{ }}
442+
";
443+
return codeText;
444+
}
440445

446+
static string createConsumerSpecific()
447+
{
448+
return
449+
createClassConstructors("ConsumerConfig") +
450+
@"
441451
/// <summary>
442452
/// A comma separated list of fields that may be optionally set
443453
/// in <see cref=""Confluent.Kafka.ConsumeResult{TKey,TValue}"" />
444454
/// objects returned by the
445455
/// <see cref=""Confluent.Kafka.Consumer{TKey,TValue}.Consume(System.TimeSpan)"" />
446-
/// method. Disabling fields that you do not require will improve
456+
/// method. Disabling fields that you do not require will improve
447457
/// throughput and reduce memory consumption. Allowed values:
448458
/// headers, timestamp, topic, all, none
449-
///
459+
///
450460
/// default: all
451461
/// importance: low
452462
/// </summary>
@@ -458,29 +468,14 @@ public ConsumerConfig() {}
458468
static string createProducerSpecific()
459469
{
460470
return
461-
@" /// <summary>
462-
/// Initialize a new empty <see cref=""ProducerConfig"" /> instance.
463-
/// </summary>
464-
public ProducerConfig() {}
465-
466-
/// <summary>
467-
/// Initialize a new <see cref=""ProducerConfig"" /> instance based on
468-
/// an existing <see cref=""ClientConfig"" /> instance.
469-
/// </summary>
470-
public ProducerConfig(ClientConfig config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
471-
472-
/// <summary>
473-
/// Initialize a new <see cref=""ProducerConfig"" /> instance based on
474-
/// an existing key/value pair collection.
475-
/// </summary>
476-
public ProducerConfig(IEnumerable<KeyValuePair<string, string>> config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
477-
471+
createClassConstructors("ProducerConfig") +
472+
@"
478473
/// <summary>
479-
/// Specifies whether or not the producer should start a background poll
474+
/// Specifies whether or not the producer should start a background poll
480475
/// thread to receive delivery reports and event notifications. Generally,
481-
/// this should be set to true. If set to false, you will need to call
476+
/// this should be set to true. If set to false, you will need to call
482477
/// the Poll function manually.
483-
///
478+
///
484479
/// default: true
485480
/// importance: low
486481
/// </summary>
@@ -490,7 +485,7 @@ public ProducerConfig() {}
490485
/// Specifies whether to enable notification of delivery reports. Typically
491486
/// you should set this parameter to true. Set it to false for ""fire and
492487
/// forget"" semantics and a small boost in performance.
493-
///
488+
///
494489
/// default: true
495490
/// importance: low
496491
/// </summary>
@@ -501,7 +496,7 @@ public ProducerConfig() {}
501496
/// reports. Disabling delivery report fields that you do not require will
502497
/// improve maximum throughput and reduce memory usage. Allowed values:
503498
/// key, value, timestamp, headers, all, none.
504-
///
499+
///
505500
/// default: all
506501
/// importance: low
507502
/// </summary>
@@ -512,24 +507,7 @@ public ProducerConfig() {}
512507

513508
static string createAdminClientSpecific()
514509
{
515-
return
516-
@" /// <summary>
517-
/// Initialize a new empty <see cref=""AdminClientConfig"" /> instance.
518-
/// </summary>
519-
public AdminClientConfig() {}
520-
521-
/// <summary>
522-
/// Initialize a new <see cref=""AdminClientConfig"" /> instance based on
523-
/// an existing <see cref=""ClientConfig"" /> instance.
524-
/// </summary>
525-
public AdminClientConfig(ClientConfig config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
526-
527-
/// <summary>
528-
/// Initialize a new <see cref=""AdminClientConfig"" /> instance based on
529-
/// an existing key/value pair collection.
530-
/// </summary>
531-
public AdminClientConfig(IEnumerable<KeyValuePair<string, string>> config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
532-
";
510+
return createClassConstructors("AdminClientConfig");
533511
}
534512

535513
static List<PropertySpecification> extractAll(string configDoc)
@@ -547,24 +525,24 @@ static List<PropertySpecification> extractAll(string configDoc)
547525
continue;
548526
}
549527

550-
var columns = line.Split('|');
528+
var columns = SplitLine(line).ToArray();
551529
if (columns.Length != 6) { continue; }
552530
if (columns[0].Contains("-----")) { continue; }
553531
if (columns[0].Contains("Property")) { continue; }
554532

555533
var prop = new PropertySpecification();
556534
prop.IsGlobal = parsingGlobal;
557-
prop.Name = columns[0].Trim();
558-
prop.CPorA = columns[1].Trim();
559-
prop.Range = columns[2].Trim();
560-
prop.Default = columns[3].Trim();
561-
prop.Importance = columns[4].Trim();
535+
prop.Name = columns[0];
536+
prop.CPorA = columns[1];
537+
prop.Range = columns[2];
538+
prop.Default = columns[3];
539+
prop.Importance = columns[4];
562540

563-
var desc = columns[5].Trim();
541+
var desc = columns[5];
564542
bool isAlias = desc.StartsWith("Alias");
565543
if (isAlias)
566544
{
567-
var firstIdx = desc.IndexOf('`')+1;
545+
var firstIdx = desc.IndexOf('`') + 1;
568546
prop.AliasFor = desc.Substring(firstIdx, desc.IndexOf('`', firstIdx) - desc.IndexOf('`') - 1);
569547
}
570548
else
@@ -582,6 +560,23 @@ static List<PropertySpecification> extractAll(string configDoc)
582560
return props;
583561
}
584562

563+
static IEnumerable<string> SplitLine(string line)
564+
{
565+
if (string.IsNullOrWhiteSpace(line))
566+
yield break;
567+
568+
int lastPipe = 0;
569+
for (int i = 1; i < line.Length - 1; i++)
570+
{
571+
if (line[i] == '|' && line[i - 1] == ' ' && line[i + 1] == ' ')
572+
{
573+
yield return line.Substring(lastPipe, i - lastPipe).Trim();
574+
lastPipe = i + 1;
575+
}
576+
}
577+
yield return line.Substring(lastPipe + 1).Trim();
578+
}
579+
585580
static List<PropertySpecification> removeDuplicateTopicLevel(List<PropertySpecification> props)
586581
{
587582
// remove topicLevel properties that are in both topic level and global.
@@ -666,6 +661,7 @@ static async Task<int> Main(string[] args)
666661
codeText += MappingConfiguration.SaslMechanismEnumString;
667662
codeText += MappingConfiguration.AcksEnumString;
668663
codeText += createClassHeader("ClientConfig", "Configuration common to all clients", false);
664+
codeText += createClassConstructors("ClientConfig");
669665
codeText += MappingConfiguration.SaslMechanismGetSetString;
670666
codeText += MappingConfiguration.AcksGetSetString;
671667
codeText += createProperties(props.Where(p => p.CPorA == "*"));

src/Confluent.Kafka/Config.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,21 @@ public class Config : IEnumerable<KeyValuePair<string, string>>
3838
/// <summary>
3939
/// Initialize a new empty <see cref="Config" /> instance.
4040
/// </summary>
41-
public Config() {}
41+
public Config() { this.properties = new Dictionary<string, string>(); }
4242

4343
/// <summary>
4444
/// Initialize a new <see cref="Config" /> instance based on
4545
/// an existing <see cref="Config" /> instance.
46+
/// This will change the values "in-place" i.e. operations on this class WILL modify the provided collection
4647
/// </summary>
47-
public Config(Config config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
48+
public Config(Config config) { this.properties = config.properties; }
4849

4950
/// <summary>
50-
/// Initialize a new <see cref="Config" /> instance based on
51-
/// an existing key/value pair collection.
51+
/// Initialize a new <see cref="Config" /> wrapping
52+
/// an existing key/value dictionary.
53+
/// This will change the values "in-place" i.e. operations on this class WILL modify the provided collection
5254
/// </summary>
53-
public Config(IEnumerable<KeyValuePair<string, string>> config) { this.properties = new Dictionary<string, string>(config.ToDictionary(a => a.Key, a => a.Value)); }
55+
public Config(IDictionary<string, string> config) { this.properties = config; }
5456

5557
/// <summary>
5658
/// Set a configuration property using a string key / value pair.
@@ -106,7 +108,7 @@ public string Get(string key)
106108
if (result == null) { return null; }
107109
return int.Parse(result);
108110
}
109-
111+
110112
/// <summary>
111113
/// Gets a configuration property bool? value given a key.
112114
/// </summary>
@@ -178,7 +180,7 @@ protected void SetObject(string name, object val)
178180
/// <summary>
179181
/// The configuration properties.
180182
/// </summary>
181-
protected Dictionary<string, string> properties = new Dictionary<string, string>();
183+
protected IDictionary<string, string> properties;
182184

183185
/// <summary>
184186
/// Returns an enumerator that iterates through the property collection.

0 commit comments

Comments
 (0)