// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. namespace System.Buffers.Text { public static partial class Utf8Parser { // // Parse an RFC1123 date string. // // 01234567890123456789012345678 // ----------------------------- // Tue, 03 Jan 2017 08:08:05 GMT // private static bool TryParseDateTimeOffsetR(ReadOnlySpan source, uint caseFlipXorMask, out DateTimeOffset dateTimeOffset, out int bytesConsumed) { if (source.Length < 29) { bytesConsumed = 0; dateTimeOffset = default; return false; } DayOfWeek dayOfWeek; { uint dow0 = source[0] ^ caseFlipXorMask; uint dow1 = source[1]; uint dow2 = source[2]; uint comma = source[3]; uint dowString = (dow0 << 24) | (dow1 << 16) | (dow2 << 8) | comma; switch (dowString) { case 0x53756E2c /* 'Sun,' */: dayOfWeek = DayOfWeek.Sunday; break; case 0x4d6f6e2c /* 'Mon,' */: dayOfWeek = DayOfWeek.Monday; break; case 0x5475652c /* 'Tue,' */: dayOfWeek = DayOfWeek.Tuesday; break; case 0x5765642c /* 'Wed,' */: dayOfWeek = DayOfWeek.Wednesday; break; case 0x5468752c /* 'Thu,' */: dayOfWeek = DayOfWeek.Thursday; break; case 0x4672692c /* 'Fri,' */: dayOfWeek = DayOfWeek.Friday; break; case 0x5361742c /* 'Sat,' */: dayOfWeek = DayOfWeek.Saturday; break; default: bytesConsumed = 0; dateTimeOffset = default; return false; } } if (source[4] != Utf8Constants.Space) { bytesConsumed = 0; dateTimeOffset = default; return false; } int day; { uint digit1 = source[5] - 48u; // '0' uint digit2 = source[6] - 48u; // '0' if (digit1 > 9 || digit2 > 9) { bytesConsumed = 0; dateTimeOffset = default; return false; } day = (int)(digit1 * 10 + digit2); } if (source[7] != Utf8Constants.Space) { bytesConsumed = 0; dateTimeOffset = default; return false; } int month; { uint mon0 = source[8] ^ caseFlipXorMask; uint mon1 = source[9]; uint mon2 = source[10]; uint space = source[11]; uint monthString = (mon0 << 24) | (mon1 << 16) | (mon2 << 8) | space; switch (monthString) { case 0x4a616e20: /* 'Jan ' */ month = 1; break; case 0x46656220: /* 'Feb ' */ month = 2; break; case 0x4d617220: /* 'Mar ' */ month = 3; break; case 0x41707220: /* 'Apr ' */ month = 4; break; case 0x4d617920: /* 'May ' */ month = 5; break; case 0x4a756e20: /* 'Jun ' */ month = 6; break; case 0x4a756c20: /* 'Jul ' */ month = 7; break; case 0x41756720: /* 'Aug ' */ month = 8; break; case 0x53657020: /* 'Sep ' */ month = 9; break; case 0x4f637420: /* 'Oct ' */ month = 10; break; case 0x4e6f7620: /* 'Nov ' */ month = 11; break; case 0x44656320: /* 'Dec ' */ month = 12; break; default: bytesConsumed = 0; dateTimeOffset = default; return false; } } int year; { uint digit1 = source[12] - 48u; // '0' uint digit2 = source[13] - 48u; // '0' uint digit3 = source[14] - 48u; // '0' uint digit4 = source[15] - 48u; // '0' if (digit1 > 9 || digit2 > 9 || digit3 > 9 || digit4 > 9) { bytesConsumed = 0; dateTimeOffset = default; return false; } year = (int)(digit1 * 1000 + digit2 * 100 + digit3 * 10 + digit4); } if (source[16] != Utf8Constants.Space) { bytesConsumed = 0; dateTimeOffset = default; return false; } int hour; { uint digit1 = source[17] - 48u; // '0' uint digit2 = source[18] - 48u; // '0' if (digit1 > 9 || digit2 > 9) { bytesConsumed = 0; dateTimeOffset = default; return false; } hour = (int)(digit1 * 10 + digit2); } if (source[19] != Utf8Constants.Colon) { bytesConsumed = 0; dateTimeOffset = default; return false; } int minute; { uint digit1 = source[20] - 48u; // '0' uint digit2 = source[21] - 48u; // '0' if (digit1 > 9 || digit2 > 9) { bytesConsumed = 0; dateTimeOffset = default; return false; } minute = (int)(digit1 * 10 + digit2); } if (source[22] != Utf8Constants.Colon) { bytesConsumed = 0; dateTimeOffset = default; return false; } int second; { uint digit1 = source[23] - 48u; // '0' uint digit2 = source[24] - 48u; // '0' if (digit1 > 9 || digit2 > 9) { bytesConsumed = 0; dateTimeOffset = default; return false; } second = (int)(digit1 * 10 + digit2); } { uint space = source[25]; uint g = source[26] ^ caseFlipXorMask; uint m = source[27] ^ caseFlipXorMask; uint t = source[28] ^ caseFlipXorMask; uint gmtString = (space << 24) | (g << 16) | (m << 8) | t; if (gmtString != 0x20474d54 /* ' GMT' */) { bytesConsumed = 0; dateTimeOffset = default; return false; } } if (!TryCreateDateTimeOffset(year: year, month: month, day: day, hour: hour, minute: minute, second: second, fraction: 0, offsetNegative: false, offsetHours: 0, offsetMinutes: 0, out dateTimeOffset)) { bytesConsumed = 0; dateTimeOffset = default; return false; } if (dayOfWeek != dateTimeOffset.DayOfWeek) { // If we got here, the day of week did not match the actual date. bytesConsumed = 0; dateTimeOffset = default; return false; } bytesConsumed = 29; return true; } } }