// // HeaderInfo.cs // // Authors: // Marek Safar // // Copyright (C) 2011, 2014 Xamarin Inc (http://www.xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Diagnostics; using System.Collections.Generic; namespace System.Net.Http.Headers { delegate bool TryParseDelegate (string value, out T result); delegate bool TryParseListDelegate (string value, int minimalCount, out List result); abstract class HeaderInfo { class HeaderTypeInfo : HeaderInfo where U : class { readonly TryParseDelegate parser; public HeaderTypeInfo (string name, TryParseDelegate parser, HttpHeaderKind headerKind) : base (name, headerKind) { this.parser = parser; } public override void AddToCollection (object collection, object value) { Debug.Assert (AllowsMany); var c = (HttpHeaderValueCollection) collection; var list = value as List; if (list != null) c.AddRange (list); else c.Add ((U) value); } protected override object CreateCollection (HttpHeaders headers, HeaderInfo headerInfo) { return new HttpHeaderValueCollection (headers, headerInfo); } public override List ToStringCollection (object collection) { if (collection == null) return null; var c = (HttpHeaderValueCollection) collection; if (c.Count == 0) { if (c.InvalidValues == null) return null; return new List (c.InvalidValues); } var list = new List (); foreach (var item in c) { list.Add (item.ToString ()); } if (c.InvalidValues != null) list.AddRange (c.InvalidValues); return list; } public override bool TryParse (string value, out object result) { T tresult; bool b = parser (value, out tresult); result = tresult; return b; } } class CollectionHeaderTypeInfo : HeaderTypeInfo where U : class { readonly int minimalCount; readonly string separator; readonly TryParseListDelegate parser; public CollectionHeaderTypeInfo (string name, TryParseListDelegate parser, HttpHeaderKind headerKind, int minimalCount, string separator) : base (name, null, headerKind) { this.parser = parser; this.minimalCount = minimalCount; AllowsMany = true; this.separator = separator; } public override string Separator { get { return separator; } } public override bool TryParse (string value, out object result) { List tresult; if (!parser (value, minimalCount, out tresult)) { result = null; return false; } result = tresult; return true; } } public bool AllowsMany; public readonly HttpHeaderKind HeaderKind; public readonly string Name; protected HeaderInfo (string name, HttpHeaderKind headerKind) { this.Name = name; this.HeaderKind = headerKind; } public static HeaderInfo CreateSingle (string name, TryParseDelegate parser, HttpHeaderKind headerKind, Func toString = null) { return new HeaderTypeInfo (name, parser, headerKind) { CustomToString = toString }; } // // Headers with #rule for defining lists of elements or *rule for defining occurences of elements // public static HeaderInfo CreateMulti (string name, TryParseListDelegate elementParser, HttpHeaderKind headerKind, int minimalCount = 1, string separator = ", ") where T : class { return new CollectionHeaderTypeInfo (name, elementParser, headerKind, minimalCount, separator); } public object CreateCollection (HttpHeaders headers) { return CreateCollection (headers, this); } public Func CustomToString { get; private set; } public virtual string Separator { get { // Needed for AllowsMany only throw new NotSupportedException (); } } public abstract void AddToCollection (object collection, object value); protected abstract object CreateCollection (HttpHeaders headers, HeaderInfo headerInfo); public abstract List ToStringCollection (object collection); public abstract bool TryParse (string value, out object result); } }