RSCG – DotnetYang

RSCG – DotnetYang    

name DotnetYang
nuget https://www.nuget.org/packages/DotnetYang/
link https://github.com/westermo/DotnetYang
author Westermo Network Technologies

Generating source code from YANG models

  

This is how you can use DotnetYang .

The code that you start with is


<project sdk="Microsoft.NET.Sdk">

  <propertygroup>
    <outputtype>Exe</outputtype>
    <targetframework>net8.0</targetframework>
    <implicitusings>enable</implicitusings>
    <nullable>enable</nullable>
  </propertygroup>

  
  <itemgroup>
    <additionalfiles include="demo.yang">
  </additionalfiles>

	 <propertygroup>
        <emitcompilergeneratedfiles>true</emitcompilergeneratedfiles>
        <compilergeneratedfilesoutputpath>$(BaseIntermediateOutputPath)\GX</compilergeneratedfilesoutputpath>
    </propertygroup>	
  <itemgroup>
    <packagereference version="0.3.0" include="dotnetYang">
  </packagereference>

</itemgroup>


The code that you will use is


Console.WriteLine("Yang file from https://info.support.huawei.com/info-finder/encyclopedia/en/YANG.html#content4!");
Some.Module.YangNode.DoSomethingInput input = new Some.Module.YangNode.DoSomethingInput
{
    TheBigLeaf = 123
};


module some-module {
    yang-version 1.1;
    namespace "urn:dotnet:yang:andrei";
    prefix sm;
    identity someIdentity;
    identity someOtherIdentity
    {
        base someIdentity;
    }
    rpc doSomething {
        input {
            leaf the-big-leaf
            {
                type uint32;
                default "4";
                description "The value that is the input of the doSomething rpc";
            }
        }
        output {
            leaf response
            {
                type identityref
                {
                    base someIdentity;
                }
                default "someOtherIdentity";
                description "The identity that is the output of the doSomething rpc";
            }
        }
    }
}

   The code that is generated is

using System;
using System.Xml;
using YangSupport;
namespace yangDemo;
///<summary>
///Configuration root object for yangDemo based on provided .yang modules
///</summary>

public class Configuration
{
    public Some.Module.YangNode? SomeModule { get; set; }
    public async Task WriteXMLAsync(XmlWriter writer)
	{
	    await writer.WriteStartElementAsync(null,"root",null);
	    
	    if(SomeModule is not null) await SomeModule.WriteXMLAsync(writer);
	    await writer.WriteEndElementAsync();
	}
    public static async Task<configuration> ParseAsync(XmlReader reader)
	{
	    Some.Module.YangNode? _SomeModule = default!;
	    while(await reader.ReadAsync())
	    {
	       switch(reader.NodeType)
	       {
	           case XmlNodeType.Element:
	               switch(reader.Name)
	               {
	                    case "some-module":
						    _SomeModule = await Some.Module.YangNode.ParseAsync(reader);
						    continue;
	                    case "rpc-error": throw await RpcException.ParseAsync(reader);
	                    default: throw new Exception($"Unexpected element '{reader.Name}' under 'root'");
	               }
	           case XmlNodeType.EndElement when reader.Name == "root":
	               return new Configuration{
	                   SomeModule = _SomeModule,
	               };
	           case XmlNodeType.Whitespace: break;
	           default: throw new Exception($"Unexpected node type '{reader.NodeType}' : '{reader.Name}' under 'root'");
	       }
	    }
	    throw new Exception("Reached end-of-readability without ever returning from Configuration.ParseAsync");
	}
}
public static class IYangServerExtensions
{
   public static async Task Receive(this IYangServer server,global::System.IO.Stream input,global::System.IO.Stream output)
   {
       var initialPosition = output.Position;
       var initialLength = output.Length;
       string? id = null;
       using XmlReader reader = XmlReader.Create(input,SerializationHelper.GetStandardReaderSettings());
       using XmlWriter writer = XmlWriter.Create(output,SerializationHelper.GetStandardWriterSettings());
       try
       {
           await reader.ReadAsync();
           switch(reader.Name)
           {
               case "rpc":
                   id = reader.ParseMessageId();
                   await writer.WriteStartElementAsync(null,"rpc-reply","urn:ietf:params:xml:ns:netconf:base:1.0");
                   await writer.WriteAttributeStringAsync(null,"message-id",null,id);
                   await reader.ReadAsync();
                   switch(reader.Name)
                   {
                       case "action":
                           await server.ReceiveAction(reader,writer);
                           break;
                       default:
                           await server.ReceiveRPC(reader,writer);
                           break;
                   }
                   await writer.WriteEndElementAsync();
                   await writer.FlushAsync();
                   break;
               case "notification":
                   var eventTime = await reader.ParseEventTime();
                   await reader.ReadAsync();
                   await server.ReceiveNotification(reader,eventTime);
                   break;
           }
       }
       catch(RpcException ex)
       {
           await writer.FlushAsync();
           output.Position = initialPosition;
           output.SetLength(initialLength);
           await ex.SerializeAsync(output,id);
       }
       catch(Exception ex)
       {
           await writer.FlushAsync();
           output.Position = initialPosition;
           output.SetLength(initialLength);
           await output.SerializeRegularExceptionAsync(ex,id);
       }
   }
   public static async Task ReceiveRPC(this IYangServer server,XmlReader reader,XmlWriter writer)
   {
       switch(reader.Name)
       {
           case "doSomething" when reader.NamespaceURI is "urn:dotnet:yang:andrei":
			{
			    var input = await Some.Module.YangNode.DoSomethingInput.ParseAsync(reader);
			    var task = server.OnDoSomething(input);
			    var response = await task;
			    await response.WriteXMLAsync(writer);
			}
			break;
       }
   }
   public static async Task ReceiveAction(this IYangServer server,XmlReader reader,XmlWriter writer)
   {
       await reader.ReadAsync();
       switch(reader.Name)
       {
           
       }
   }
   public static async Task ReceiveNotification(this IYangServer server,XmlReader reader,DateTime eventTime)
   {
       switch(reader.Name)
       {
           
           
       }
   }
}
using System;
using System.Xml;
using System.Text;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using YangSupport;
namespace yangDemo
{
    public partial interface IYangServer
    {
        Task<some.module.yangnode.dosomethingoutput> OnDoSomething(Some.Module.YangNode.DoSomethingInput input);
    }
}
namespace Some.Module{
public class YangNode
{
    public const string ModuleName = "some-module";
    public const string Revision = "";
    public static string[] Features = [];
    //Yang Version 1.1
	public const string Namespace = "urn:dotnet:yang:andrei";
	public static string GetEncodedValue(SomeIdentityIdentity value)
	{
	    switch(value)
	    {
	        case SomeIdentityIdentity.SomeIdentity: return "someIdentity";
			case SomeIdentityIdentity.SomeOtherIdentity: return "someOtherIdentity";
	        default: return value.ToString();
	    }
	}
	public static string GetEncodedValue(SomeIdentityIdentity? value) =&gt; GetEncodedValue(value!.Value!);
	public static SomeIdentityIdentity GetSomeIdentityIdentityValue(string value)
	{
	    switch(value)
	    {
	        case "someIdentity": return SomeIdentityIdentity.SomeIdentity;
			case "someOtherIdentity": return SomeIdentityIdentity.SomeOtherIdentity;
	        default: throw new Exception($"{value} is not a valid value for SomeIdentityIdentity");
	    }
	}
	public enum SomeIdentityIdentity
	{
	    SomeIdentity,
		SomeOtherIdentity
	}
	public static string GetEncodedValue(SomeOtherIdentityIdentity value)
	{
	    switch(value)
	    {
	        case SomeOtherIdentityIdentity.SomeOtherIdentity: return "someOtherIdentity";
	        default: return value.ToString();
	    }
	}
	public static string GetEncodedValue(SomeOtherIdentityIdentity? value) =&gt; GetEncodedValue(value!.Value!);
	public static SomeOtherIdentityIdentity GetSomeOtherIdentityIdentityValue(string value)
	{
	    switch(value)
	    {
	        case "someOtherIdentity": return SomeOtherIdentityIdentity.SomeOtherIdentity;
	        default: throw new Exception($"{value} is not a valid value for SomeOtherIdentityIdentity");
	    }
	}
	public enum SomeOtherIdentityIdentity
	{
	    SomeOtherIdentity
	}
	public static async Task<some.module.yangnode.dosomethingoutput> DoSomething(IChannel channel,int messageID,Some.Module.YangNode.DoSomethingInput input)
	{
	    using XmlWriter writer = XmlWriter.Create(channel.WriteStream,SerializationHelper.GetStandardWriterSettings());
	    await writer.WriteStartElementAsync(null,"rpc","urn:ietf:params:xml:ns:netconf:base:1.0");
	    await writer.WriteAttributeStringAsync(null,"message-id",null,messageID.ToString());
	    await writer.WriteStartElementAsync("","doSomething","urn:dotnet:yang:andrei");
		await input.WriteXMLAsync(writer);
	    await writer.WriteEndElementAsync();
	    await writer.WriteEndElementAsync();
	    await writer.FlushAsync();
	    await channel.Send();
	    using XmlReader reader = XmlReader.Create(channel.ReadStream,SerializationHelper.GetStandardReaderSettings());
	    await reader.ReadAsync();
	    if(reader.NodeType != XmlNodeType.Element || reader.Name != "rpc-reply" || reader.NamespaceURI != "urn:ietf:params:xml:ns:netconf:base:1.0" || reader["message-id"] != messageID.ToString())
	    {
	        throw new Exception($"Expected stream to start with a <rpc-reply> element with message id {messageID} &amp; \"urn:ietf:params:xml:ns:netconf:base:1.0\" but got {reader.NodeType}: {reader.Name} in {reader.NamespaceURI}");
	    }
		var value = await DoSomethingOutput.ParseAsync(reader);
	    return value;
	}
	public class DoSomethingOutput
	{
	    ///<summary>
		///The identity that is the output of the doSomething rpc
		///</summary>
		public SomeIdentityIdentity? Response { get; set; } = SomeIdentityIdentity.SomeOtherIdentity;
	    public static async Task<dosomethingoutput> ParseAsync(XmlReader reader)
	{
	    SomeIdentityIdentity? _Response = default!;
	    while(await reader.ReadAsync())
	    {
	       switch(reader.NodeType)
	       {
	           case XmlNodeType.Element:
	               switch(reader.Name)
	               {
	                    case "response":
						    await reader.ReadAsync();
							if(reader.NodeType != XmlNodeType.Text)
							{
							    throw new Exception($"Expected token in ParseCall for 'response' to be text,but was '{reader.NodeType}'");
							}
							_Response = GetSomeIdentityIdentityValue(await reader.GetValueAsync());
							if(!reader.IsEmptyElement)
							{
							    await reader.ReadAsync();
							    if(reader.NodeType != XmlNodeType.EndElement)
							    {
							        throw new Exception($"Expected token in ParseCall for 'response' to be an element closure,but was '{reader.NodeType}'");
							    }
							}
						    continue;
	                    case "rpc-error": throw await RpcException.ParseAsync(reader);
	                    default: throw new Exception($"Unexpected element '{reader.Name}' under 'rpc-reply'");
	               }
	           case XmlNodeType.EndElement when reader.Name == "rpc-reply":
	               return new DoSomethingOutput{
	                   Response = _Response,
	               };
	           case XmlNodeType.Whitespace: break;
	           default: throw new Exception($"Unexpected node type '{reader.NodeType}' : '{reader.Name}' under 'rpc-reply'");
	       }
	    }
	    throw new Exception("Reached end-of-readability without ever returning from DoSomethingOutput.ParseAsync");
	}
	    public async Task WriteXMLAsync(XmlWriter writer)
	{
	    if(Response != default)
		{
		    await writer.WriteStartElementAsync(null,"response","urn:dotnet:yang:andrei");
		    await writer.WriteStringAsync(YangNode.GetEncodedValue(Response!));
		    await writer.WriteEndElementAsync();
		}
	}
	}
	public class DoSomethingInput
	{
	    ///<summary>
		///The value that is the input of the doSomething rpc
		///</summary>
		public uint? TheBigLeaf { get; set; } = 4;
	    public async Task WriteXMLAsync(XmlWriter writer)
		{
		    if(TheBigLeaf != default)
			{
			    await writer.WriteStartElementAsync(null,"the-big-leaf","urn:dotnet:yang:andrei");
			    await writer.WriteStringAsync(TheBigLeaf!.ToString());
			    await writer.WriteEndElementAsync();
			}
		}
	    public static async Task<dosomethinginput> ParseAsync(XmlReader reader)
		{
		    uint? _TheBigLeaf = default!;
		    while(await reader.ReadAsync())
		    {
		       switch(reader.NodeType)
		       {
		           case XmlNodeType.Element:
		               switch(reader.Name)
		               {
		                    case "the-big-leaf":
							    await reader.ReadAsync();
								if(reader.NodeType != XmlNodeType.Text)
								{
								    throw new Exception($"Expected token in ParseCall for 'the-big-leaf' to be text,but was '{reader.NodeType}'");
								}
								_TheBigLeaf = uint.Parse(await reader.GetValueAsync());
								if(!reader.IsEmptyElement)
								{
								    await reader.ReadAsync();
								    if(reader.NodeType != XmlNodeType.EndElement)
								    {
								        throw new Exception($"Expected token in ParseCall for 'the-big-leaf' to be an element closure,but was '{reader.NodeType}'");
								    }
								}
							    continue;
		                    case "rpc-error": throw await RpcException.ParseAsync(reader);
		                    default: throw new Exception($"Unexpected element '{reader.Name}' under 'doSomething'");
		               }
		           case XmlNodeType.EndElement when reader.Name == "doSomething":
		               return new DoSomethingInput{
		                   TheBigLeaf = _TheBigLeaf,
		               };
		           case XmlNodeType.Whitespace: break;
		           default: throw new Exception($"Unexpected node type '{reader.NodeType}' : '{reader.Name}' under 'doSomething'");
		       }
		    }
		    throw new Exception("Reached end-of-readability without ever returning from DoSomethingInput.ParseAsync");
		}
	}
    public static async Task<some.module.yangnode> ParseAsync(XmlReader reader)
	{
	    while(await reader.ReadAsync())
	    {
	       switch(reader.NodeType)
	       {
	           case XmlNodeType.Element:
	               switch(reader.Name)
	               {
	                    case "rpc-error": throw await RpcException.ParseAsync(reader);
	                    default: throw new Exception($"Unexpected element '{reader.Name}' under 'some-module'");
	               }
	           case XmlNodeType.EndElement when reader.Name == "some-module":
	               return new Some.Module.YangNode{
	               };
	           case XmlNodeType.Whitespace: break;
	           default: throw new Exception($"Unexpected node type '{reader.NodeType}' : '{reader.Name}' under 'some-module'");
	       }
	    }
	    throw new Exception("Reached end-of-readability without ever returning from Some.Module.YangNode.ParseAsync");
	}
    public async Task WriteXMLAsync(XmlWriter writer)
	{
	    await writer.WriteStartElementAsync(null,"some-module","urn:dotnet:yang:andrei");
	    await writer.WriteEndElementAsync();
	}
}
}

Code and pdf at

https://ignatandrei.github.io/RSCG_Examples/v2/docs/DotnetYang


Posted

in

,

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *