@@ -121,13 +121,13 @@ public IPAddress(long newAddress)
121121 /// Constructor for an IPv6 Address with a specified Scope.
122122 /// </para>
123123 /// </devdoc>
124- public IPAddress ( byte [ ] address , long scopeid )
124+ public IPAddress ( byte [ ] address , long scopeid ) :
125+ this ( new ReadOnlySpan < byte > ( address ?? throw new ArgumentNullException ( nameof ( address ) ) ) , scopeid )
125126 {
126- if ( address == null )
127- {
128- throw new ArgumentNullException ( nameof ( address ) ) ;
129- }
127+ }
130128
129+ public IPAddress ( ReadOnlySpan < byte > address , long scopeid )
130+ {
131131 if ( address . Length != IPAddressParserStatics . IPv6AddressBytes )
132132 {
133133 throw new ArgumentException ( SR . dns_bad_ip_address , nameof ( address ) ) ;
@@ -200,12 +200,13 @@ private IPAddress(ushort[] numbers, uint scopeid)
200200 /// Constructor for IPv4 and IPv6 Address.
201201 /// </para>
202202 /// </devdoc>
203- public IPAddress ( byte [ ] address )
203+ public IPAddress ( byte [ ] address ) :
204+ this ( new ReadOnlySpan < byte > ( address ?? throw new ArgumentNullException ( nameof ( address ) ) ) )
205+ {
206+ }
207+
208+ public IPAddress ( ReadOnlySpan < byte > address )
204209 {
205- if ( address == null )
206- {
207- throw new ArgumentNullException ( nameof ( address ) ) ;
208- }
209210 if ( address . Length != IPAddressParserStatics . IPv4AddressBytes && address . Length != IPAddressParserStatics . IPv6AddressBytes )
210211 {
211212 throw new ArgumentException ( SR . dns_bad_ip_address , nameof ( address ) ) ;
@@ -262,48 +263,99 @@ internal IPAddress(int newAddress)
262263 /// </devdoc>
263264 public static bool TryParse ( string ipString , out IPAddress address )
264265 {
265- address = IPAddressParser . Parse ( ipString , true ) ;
266+ if ( ipString == null )
267+ {
268+ address = null ;
269+ return false ;
270+ }
271+
272+ address = IPAddressParser . Parse ( ipString , tryParse : true ) ;
273+ return ( address != null ) ;
274+ }
275+
276+ public static bool TryParse ( ReadOnlySpan < char > ipSpan , out IPAddress address )
277+ {
278+ address = IPAddressParser . Parse ( ipSpan , tryParse : true ) ;
266279 return ( address != null ) ;
267280 }
268281
269282 public static IPAddress Parse ( string ipString )
270283 {
271- return IPAddressParser . Parse ( ipString , false ) ;
284+ if ( ipString == null )
285+ {
286+ throw new ArgumentNullException ( nameof ( ipString ) ) ;
287+ }
288+
289+ return IPAddressParser . Parse ( ipString , tryParse : false ) ;
272290 }
273291
274- /// <devdoc>
275- /// <para>
276- /// Provides a copy of the IPAddress internals as an array of bytes.
277- /// </para>
278- /// </devdoc>
279- public byte [ ] GetAddressBytes ( )
292+ public static IPAddress Parse ( ReadOnlySpan < char > ipSpan )
293+ {
294+ return IPAddressParser . Parse ( ipSpan , tryParse : false ) ;
295+ }
296+
297+ public bool TryWriteBytes ( Span < byte > destination , out int bytesWritten )
280298 {
281- byte [ ] bytes ;
282299 if ( IsIPv6 )
283300 {
284301 Debug . Assert ( _numbers != null && _numbers . Length == NumberOfLabels ) ;
285302
286- bytes = new byte [ IPAddressParserStatics . IPv6AddressBytes ] ;
303+ if ( destination . Length < IPAddressParserStatics . IPv6AddressBytes )
304+ {
305+ bytesWritten = 0 ;
306+ return false ;
307+ }
308+
287309 int j = 0 ;
288310 for ( int i = 0 ; i < NumberOfLabels ; i ++ )
289311 {
290- bytes [ j ++ ] = ( byte ) ( ( _numbers [ i ] >> 8 ) & 0xFF ) ;
291- bytes [ j ++ ] = ( byte ) ( ( _numbers [ i ] ) & 0xFF ) ;
312+ destination [ j ++ ] = ( byte ) ( ( _numbers [ i ] >> 8 ) & 0xFF ) ;
313+ destination [ j ++ ] = ( byte ) ( ( _numbers [ i ] ) & 0xFF ) ;
292314 }
315+
316+ bytesWritten = IPAddressParserStatics . IPv6AddressBytes ;
293317 }
294318 else
295319 {
296- uint address = PrivateAddress ;
297- bytes = new byte [ IPAddressParserStatics . IPv4AddressBytes ] ;
320+ if ( destination . Length < IPAddressParserStatics . IPv4AddressBytes )
321+ {
322+ bytesWritten = 0 ;
323+ return false ;
324+ }
298325
326+ uint address = PrivateAddress ;
299327 unchecked
300328 {
301- bytes [ 0 ] = ( byte ) ( address ) ;
302- bytes [ 1 ] = ( byte ) ( address >> 8 ) ;
303- bytes [ 2 ] = ( byte ) ( address >> 16 ) ;
304- bytes [ 3 ] = ( byte ) ( address >> 24 ) ;
329+ destination [ 0 ] = ( byte ) ( address ) ;
330+ destination [ 1 ] = ( byte ) ( address >> 8 ) ;
331+ destination [ 2 ] = ( byte ) ( address >> 16 ) ;
332+ destination [ 3 ] = ( byte ) ( address >> 24 ) ;
305333 }
334+
335+ bytesWritten = IPAddressParserStatics . IPv4AddressBytes ;
336+ }
337+
338+ return true ;
339+ }
340+ /// <devdoc>
341+ /// <para>
342+ /// Provides a copy of the IPAddress internals as an array of bytes.
343+ /// </para>
344+ /// </devdoc>
345+ public byte [ ] GetAddressBytes ( )
346+ {
347+ if ( IsIPv6 )
348+ {
349+ Debug . Assert ( _numbers != null && _numbers . Length == NumberOfLabels ) ;
306350 }
351+
352+ int length = IsIPv6 ? IPAddressParserStatics . IPv6AddressBytes : IPAddressParserStatics . IPv4AddressBytes ;
353+ var bytes = new byte [ length ] ;
354+
355+ bool result = TryWriteBytes ( new Span < byte > ( bytes ) , out int bytesWritten ) ;
356+
357+ Debug . Assert ( result ) ;
358+
307359 return bytes ;
308360 }
309361
@@ -369,6 +421,13 @@ public override string ToString()
369421 return _toString ;
370422 }
371423
424+ public bool TryFormat ( Span < char > destination , out int charsWritten )
425+ {
426+ return IsIPv4 ?
427+ IPAddressParser . IPv4AddressToString ( PrivateAddress , destination , out charsWritten ) :
428+ IPAddressParser . IPv6AddressToString ( _numbers , PrivateScopeId , destination , out charsWritten ) ;
429+ }
430+
372431 public static long HostToNetworkOrder ( long host )
373432 {
374433#if BIGENDIAN
0 commit comments