1 // Written in the D programming language.
2 
3 /**
4 A type for representing the name object of the 9P / Styx protocol. 
5 
6 Copyright: LightHouse Software, 2021
7 License:   $(HTTP https://github.com/aquaratixc/ESL-License, Experimental Software License 1.0).
8 Authors:   Oleg Bakharev,
9 		   Ilya Pertsev
10 */
11 module styx2000.protobj.nwname;
12 
13 private {
14 	import std.conv : to;
15 	import std.path : buildPath;
16 	import std..string : format;
17 	
18 	import styx2000.lowlevel.endianness;
19 	import styx2000.lowlevel.vls;
20 	
21 	import styx2000.protobj.styxobject;
22 }
23 
24 /**
25 	A class that provides a type for the Nwname field in some Styx messages. Inherits methods from the StyxObject class. 
26 	See_Also:
27 		https://web.archive.org/web/20201029184954/https://powerman.name/Inferno/man/5/0intro.html
28 */
29 class Nwname : StyxObject
30 {
31 	protected {
32 		string[] _nwname;
33 		
34 		ubyte[] _representation;
35 	}
36 	
37 	private {
38 		// update names list
39 		void updateNames()
40 		{
41 			if (_nwname.length == 0)
42 			{
43 				// ????
44 				// if empty walk then nwname = 1, wname = [0, 0] (in inferno)
45 				// in plan9 is [0, 0]
46 				_representation = [0, 0];
47 			}
48 			else
49 			{
50 				_representation = toLEBytes!ushort(
51 					cast(ushort) _nwname.length
52 				);
53 				foreach (e; _nwname)
54 				{
55 					_representation ~= VariableLengthSequence.pack(cast(ubyte[]) e);
56 				}
57 			}
58 		}
59 	}
60 	
61 	/**
62 	A constructor that creates an object of the Nwname class with the given parameter in the form of string's array. 
63 	If called without parameters, then the default parameter is empty string's array. 
64     Params:
65     nwname = Full file path as string's array.
66     
67     Typical usage:
68     ----
69     Nwname nwname = new Nwname([`test`]);
70     ----
71     */
72 	this(string[] nwname = [])
73 	{
74 		_nwname = nwname;
75 		_representation = [];
76 		updateNames;
77 	}
78 	
79 	/// Set name to Nwname objects as string's array
80 	void setName(string[] nwname...)
81 	{
82 		_nwname = nwname;
83 		_representation = [];
84 		updateNames;
85 	}
86 	
87 	/// Number of names in path
88 	ushort countOfNames()
89 	{
90 		return fromLEBytes!ushort(_representation[0..2]);
91 	}
92 
93 	/// Get all names in path as string's array
94 	string[] getName()
95 	{
96 		return _nwname;
97 	}
98 	
99 	/// An alias that allows you to call a getter method without accessing the base Name class
100 	alias getNwname = getName;	
101 	/// An alias that allows you to call a setter method without accessing the base Name class
102 	alias setNwname = setName;	
103 	
104 	/// Pack to bytes array
105 	ubyte[] pack()
106 	{
107 		return _representation;
108 	}
109 	
110 	/// Unpack from bytes array
111 	void unpack(ubyte[] bytes...)
112 	{
113 		_representation = bytes;
114 		_nwname = [];
115 		ushort length = fromLEBytes!ushort(bytes[0..2]);
116 		auto vlsPosition = 2;
117 		
118 		foreach (_; 0..length)
119 		{
120 			string n = cast(string) VariableLengthSequence.unpack(
121 				bytes[vlsPosition..$]
122 			);
123 			_nwname ~= n;
124 			vlsPosition += n.length + 2;
125 		}
126 	}
127 	
128 	/// Convenient string representation of an object for printing 
129 	override string toString()
130 	{
131 		return format(
132 			`Nwname(nwname=%d, wmname="%s")`,
133 			fromLEBytes!ushort(_representation[0..2]),
134 			buildPath(_nwname)
135 		);
136 	}
137 	
138 	/// An alias for easier packing into a byte array without having to manually call the pack() method
139 	alias pack this;
140 }