diff --git a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs index 57a96cd..9607cc0 100644 --- a/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs +++ b/src/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs @@ -86,22 +86,51 @@ public static SkStackActiveScanOptions Create( scanDurationGenerator: scanDurationGenerator ); + /// + /// Creates the with the custom selection method and the delegate for generating duration factor. + /// + /// A delegate to method that iterates the scan durations. + /// + /// A callback to select the target PAA from the PAAs found during the scan. + /// If , selects the PAA which found at first during the scan. + /// + public static SkStackActiveScanOptions Create( + Func> scanDurationGeneratorFunc, + Predicate? paaSelector = null + ) + => new UserDefinedActiveScanOptions( + paaSelector: paaSelector, + scanDurationGeneratorFunc: scanDurationGeneratorFunc + ); + private sealed class UserDefinedActiveScanOptions : SkStackActiveScanOptions { private readonly Predicate? paaSelector; - private readonly IEnumerable scanDurationGenerator; + private readonly Func> scanDurationGeneratorFunc; public UserDefinedActiveScanOptions( Predicate? paaSelector, IEnumerable scanDurationGenerator ) + { + if (scanDurationGenerator is null) + throw new ArgumentNullException(nameof(scanDurationGenerator)); + + this.paaSelector = paaSelector; + this.scanDurationGeneratorFunc = new(() => scanDurationGenerator); + } + + public UserDefinedActiveScanOptions( + Predicate? paaSelector, + Func> scanDurationGeneratorFunc + ) { this.paaSelector = paaSelector; - this.scanDurationGenerator = scanDurationGenerator ?? throw new ArgumentNullException(nameof(scanDurationGenerator)); + this.scanDurationGeneratorFunc = scanDurationGeneratorFunc ?? throw new ArgumentNullException(nameof(scanDurationGeneratorFunc)); } - public override SkStackActiveScanOptions Clone() => new UserDefinedActiveScanOptions(paaSelector, scanDurationGenerator.ToArray()); + public override SkStackActiveScanOptions Clone() => new UserDefinedActiveScanOptions(paaSelector, scanDurationGeneratorFunc); internal override bool SelectPanaAuthenticationAgent(SkStackPanDescription desc) => paaSelector?.Invoke(desc) ?? true; - internal override IEnumerable YieldScanDurationFactors() => scanDurationGenerator; + internal override IEnumerable YieldScanDurationFactors() => scanDurationGeneratorFunc(); } /// @@ -120,22 +149,50 @@ PhysicalAddress paaMacAddress scanDurationGenerator: scanDurationGenerator ); + /// + /// Creates the with the custom selection method and the delegate for generating duration factor. + /// + /// A delegate to method that iterates the scan durations. + /// + /// A of the target PAA. This method selects the first PAA found during the scan that matches this . + /// + public static SkStackActiveScanOptions Create( + Func> scanDurationGeneratorFunc, + PhysicalAddress paaMacAddress + ) + => new FindByMacAddressActiveScanOptions( + paaMacAddress: paaMacAddress, + scanDurationGeneratorFunc: scanDurationGeneratorFunc + ); + private sealed class FindByMacAddressActiveScanOptions : SkStackActiveScanOptions { private readonly PhysicalAddress paaMacAddress; - private readonly IEnumerable scanDurationGenerator; + private readonly Func> scanDurationGeneratorFunc; public FindByMacAddressActiveScanOptions( PhysicalAddress paaMacAddress, IEnumerable scanDurationGenerator ) + { + if (scanDurationGenerator is null) + throw new ArgumentNullException(nameof(scanDurationGenerator)); + + this.paaMacAddress = paaMacAddress; + scanDurationGeneratorFunc = new(() => scanDurationGenerator); + } + + public FindByMacAddressActiveScanOptions( + PhysicalAddress paaMacAddress, + Func> scanDurationGeneratorFunc + ) { this.paaMacAddress = paaMacAddress; - this.scanDurationGenerator = scanDurationGenerator ?? throw new ArgumentNullException(nameof(scanDurationGenerator)); + this.scanDurationGeneratorFunc = scanDurationGeneratorFunc ?? throw new ArgumentNullException(nameof(scanDurationGeneratorFunc)); } - public override SkStackActiveScanOptions Clone() => new FindByMacAddressActiveScanOptions(paaMacAddress, scanDurationGenerator.ToArray()); + public override SkStackActiveScanOptions Clone() => new FindByMacAddressActiveScanOptions(paaMacAddress, scanDurationGeneratorFunc); internal override bool SelectPanaAuthenticationAgent(SkStackPanDescription desc) => desc.MacAddress.Equals(paaMacAddress); - internal override IEnumerable YieldScanDurationFactors() => scanDurationGenerator; + internal override IEnumerable YieldScanDurationFactors() => scanDurationGeneratorFunc(); } /* diff --git a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs index 069165c..de50a80 100644 --- a/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs +++ b/tests/Smdn.Net.SkStackIP/Smdn.Net.SkStackIP/SkStackActiveScanOptions.cs @@ -51,4 +51,29 @@ public void YieldScanDurationFactors_Create_ScanDurationGenerator_WithPaaMacAddr () => TestYieldScanDurationFactors(SkStackActiveScanOptions.Create(scanDurationFactors!, paaMacAddress: PhysicalAddress.None), scanDurationFactors!), typeOfExpectedException is null ? Throws.Nothing : Throws.TypeOf(typeOfExpectedException) ); + + [Test] + public void YieldScanDurationFactors_Create_ScanDurationGeneratorFunc_ArgumentNull() + { + Assert.That(() => SkStackActiveScanOptions.Create(scanDurationGeneratorFunc: null!, paaSelector: null), Throws.ArgumentNullException); + Assert.That(() => SkStackActiveScanOptions.Create(scanDurationGeneratorFunc: null!, paaMacAddress: PhysicalAddress.None), Throws.ArgumentNullException); + } + + [TestCase(new int[0])] + [TestCase(new int[] { 1 })] + [TestCase(new int[] { 1, 2, 3, 4, 5 })] + public void YieldScanDurationFactors_Create_ScanDurationGeneratorFunc_WithPaaSelector(int[] scanDurationFactors) + => Assert.That( + () => TestYieldScanDurationFactors(SkStackActiveScanOptions.Create(scanDurationGeneratorFunc: () => scanDurationFactors, paaSelector: null), scanDurationFactors!), + Throws.Nothing + ); + + [TestCase(new int[0])] + [TestCase(new int[] { 1 })] + [TestCase(new int[] { 1, 2, 3, 4, 5 })] + public void YieldScanDurationFactors_Create_ScanDurationGeneratorFunc_WithPaaMacAddress(int[] scanDurationFactors) + => Assert.That( + () => TestYieldScanDurationFactors(SkStackActiveScanOptions.Create(scanDurationGeneratorFunc: () => scanDurationFactors, paaMacAddress: PhysicalAddress.None), scanDurationFactors!), + Throws.Nothing + ); }