|
| 1 | +// This source code is dual-licensed under the Apache License, version |
| 2 | +// 2.0, and the Mozilla Public License, version 2.0. |
| 3 | +// |
| 4 | +// The APL v2.0: |
| 5 | +// |
| 6 | +//--------------------------------------------------------------------------- |
| 7 | +// Copyright (c) 2007-2020 VMware, Inc. |
| 8 | +// |
| 9 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 10 | +// you may not use this file except in compliance with the License. |
| 11 | +// You may obtain a copy of the License at |
| 12 | +// |
| 13 | +// https://www.apache.org/licenses/LICENSE-2.0 |
| 14 | +// |
| 15 | +// Unless required by applicable law or agreed to in writing, software |
| 16 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 17 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 18 | +// See the License for the specific language governing permissions and |
| 19 | +// limitations under the License. |
| 20 | +//--------------------------------------------------------------------------- |
| 21 | +// |
| 22 | +// The MPL v2.0: |
| 23 | +// |
| 24 | +//--------------------------------------------------------------------------- |
| 25 | +// This Source Code Form is subject to the terms of the Mozilla Public |
| 26 | +// License, v. 2.0. If a copy of the MPL was not distributed with this |
| 27 | +// file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| 28 | +// |
| 29 | +// Copyright (c) 2011-2020 VMware, Inc. or its affiliates. All rights reserved. |
| 30 | +//--------------------------------------------------------------------------- |
| 31 | + |
| 32 | +using System; |
| 33 | +using System.Text; |
| 34 | +using System.Text.RegularExpressions; |
| 35 | + |
| 36 | +namespace RabbitMQ.Client |
| 37 | +{ |
| 38 | + public abstract class AmqpString |
| 39 | + { |
| 40 | + private readonly string _value; |
| 41 | + private readonly ReadOnlyMemory<byte> _stringBytes; |
| 42 | + |
| 43 | + public AmqpString() |
| 44 | + { |
| 45 | + _value = string.Empty; |
| 46 | + _stringBytes = ReadOnlyMemory<byte>.Empty; |
| 47 | + } |
| 48 | + |
| 49 | + public AmqpString(string value, ushort maxLen, Encoding encoding) |
| 50 | + : this(value, maxLen, encoding, null) |
| 51 | + { |
| 52 | + } |
| 53 | + |
| 54 | + public AmqpString(string value, ushort maxLen, Encoding encoding, string validatorRegex) |
| 55 | + { |
| 56 | + if (value.Length > maxLen) |
| 57 | + { |
| 58 | + throw new ArgumentOutOfRangeException(nameof(value)); |
| 59 | + } |
| 60 | + |
| 61 | + if (false == string.IsNullOrWhiteSpace(validatorRegex)) |
| 62 | + { |
| 63 | + var re = new Regex(validatorRegex); |
| 64 | + if (false == re.IsMatch(value)) |
| 65 | + { |
| 66 | + throw new ArgumentOutOfRangeException(nameof(value)); |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + if (encoding == Encoding.ASCII) |
| 71 | + { |
| 72 | + if (false == isAscii(value)) |
| 73 | + { |
| 74 | + throw new ArgumentOutOfRangeException(nameof(value)); |
| 75 | + } |
| 76 | + } |
| 77 | + |
| 78 | + _value = value; |
| 79 | + _stringBytes = new ReadOnlyMemory<byte>(encoding.GetBytes(value)); |
| 80 | + } |
| 81 | + |
| 82 | + public override string ToString() |
| 83 | + { |
| 84 | + return _value; |
| 85 | + } |
| 86 | + |
| 87 | + public static implicit operator string(AmqpString amqpString) |
| 88 | + { |
| 89 | + return amqpString._value; |
| 90 | + } |
| 91 | + |
| 92 | + public static implicit operator ReadOnlyMemory<byte>(AmqpString amqpString) |
| 93 | + { |
| 94 | + return amqpString._stringBytes; |
| 95 | + } |
| 96 | + |
| 97 | + private bool isAscii(string value) |
| 98 | + { |
| 99 | + return Encoding.UTF8.GetByteCount(value) == value.Length; |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + /* |
| 104 | + * From the spec: |
| 105 | + * <domain name="exchange-name" type="shortstr" label="exchange name"> |
| 106 | + * <doc> The exchange name is a client-selected string that identifies the exchange for publish methods. </doc> |
| 107 | + * <assert check="length" value="127"/> |
| 108 | + * <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/> |
| 109 | + * </domain> |
| 110 | + */ |
| 111 | + public class ExchangeName : AmqpString |
| 112 | + { |
| 113 | + public static readonly ExchangeName Empty = new ExchangeName(); |
| 114 | + |
| 115 | + public ExchangeName() : base() |
| 116 | + { |
| 117 | + } |
| 118 | + |
| 119 | + public ExchangeName(string exchangeName) |
| 120 | + : base(exchangeName, 127, Encoding.ASCII, "^[a-zA-Z0-9-_.:]*$") |
| 121 | + { |
| 122 | + } |
| 123 | + |
| 124 | + public static explicit operator ExchangeName(string value) |
| 125 | + { |
| 126 | + return new ExchangeName(value); |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + /* |
| 131 | + * From the spec: |
| 132 | + * <domain name="queue-name" type="shortstr" label="queue name"> |
| 133 | + * <doc> The queue name identifies the queue within the vhost. In methods where the queue name may be blank, and that has no specific significance, this refers to the 'current' queue for the channel, meaning the last queue that the client declared on the channel. If the client did not declare a queue, and the method needs a queue name, this will result in a 502 (syntax error) channel exception. </doc> |
| 134 | + * <assert check="length" value="127"/> |
| 135 | + * <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/> |
| 136 | + * </domain> |
| 137 | + */ |
| 138 | + public class QueueName : AmqpString |
| 139 | + { |
| 140 | + public static readonly QueueName Empty = new QueueName(); |
| 141 | + |
| 142 | + public QueueName() : base() |
| 143 | + { |
| 144 | + } |
| 145 | + |
| 146 | + public QueueName(string exchangeName) |
| 147 | + : base(exchangeName, 127, Encoding.ASCII, "^[a-zA-Z0-9-_.:]*$") |
| 148 | + { |
| 149 | + } |
| 150 | + |
| 151 | + public static explicit operator QueueName(string value) |
| 152 | + { |
| 153 | + return new QueueName(value); |
| 154 | + } |
| 155 | + } |
| 156 | + |
| 157 | + /* |
| 158 | + * From the spec: |
| 159 | + * <field name="routing-key" domain="shortstr" label="Message routing key"> |
| 160 | + * <doc> Specifies the routing key for the message. The routing key is used for routing messages depending on the exchange configuration. </doc> |
| 161 | + * </field> |
| 162 | + * <domain name = "shortstr" type="shortstr" label="short string (max. 256 characters)"/> |
| 163 | + */ |
| 164 | + public class RoutingKey : AmqpString |
| 165 | + { |
| 166 | + public static readonly RoutingKey Empty = new RoutingKey(); |
| 167 | + |
| 168 | + public RoutingKey() : base() |
| 169 | + { |
| 170 | + } |
| 171 | + |
| 172 | + public RoutingKey(string exchangeName) |
| 173 | + : base(exchangeName, 256, Encoding.ASCII) |
| 174 | + { |
| 175 | + } |
| 176 | + |
| 177 | + public static explicit operator RoutingKey(string value) |
| 178 | + { |
| 179 | + return new RoutingKey(value); |
| 180 | + } |
| 181 | + } |
| 182 | +} |
0 commit comments