1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one
3  *  or more contributor license agreements.  See the NOTICE file
4  *  distributed with this work for additional information
5  *  regarding copyright ownership.  The ASF licenses this file
6  *  to you under the Apache License, Version 2.0 (the
7  *  "License"); you may not use this file except in compliance
8  *  with the License.  You may obtain a copy of the License at
9  *
10  *    http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing,
13  *  software distributed under the License is distributed on an
14  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  *  KIND, either express or implied.  See the License for the
16  *  specific language governing permissions and limitations
17  *  under the License.
18  *
19  */
20 module hunt.net.codec.textline.TextLineEncoder;
21 
22 import hunt.net.codec.textline.LineDelimiter;
23 import hunt.net.codec.Encoder;
24 import hunt.net.Connection;
25 
26 import hunt.io.ByteBuffer;
27 import hunt.io.BufferUtils;
28 import hunt.Exceptions;
29 
30 import std.conv;
31 
32 
33 /**
34  * A {@link ProtocolEncoder} which encodes a string into a text line
35  * which ends with the delimiter.
36  *
37  * @author <a href="http://mina.apache.org">Apache MINA Project</a>
38  */
39 class TextLineEncoder : EncoderChain {
40     private enum string ENCODER = "encoder";
41 
42     private LineDelimiter delimiter;
43 
44     private int maxLineLength = int.max;
45 
46     /**
47      * Creates a new instance with the current default {@link Charset}
48      * and {@link LineDelimiter#UNIX} delimiter.
49      */
50     this() {
51         this(LineDelimiter.UNIX);
52     }
53 
54     /**
55      * Creates a new instance with the current default {@link Charset}
56      * and the specified <tt>delimiter</tt>.
57      * 
58      * @param delimiter The line delimiter to use
59      */
60     this(string delimiter) {
61         this(LineDelimiter(delimiter));
62     }
63 
64     /**
65      * Creates a new instance with the current default {@link Charset}
66      * and the specified <tt>delimiter</tt>.
67      * 
68      * @param delimiter The line delimiter to use
69      */
70     this(LineDelimiter delimiter) {
71         if (LineDelimiter.AUTO == delimiter) {
72             throw new IllegalArgumentException("AUTO delimiter is not allowed for encoder.");
73         }
74 
75         this.delimiter = delimiter;        
76     }
77 
78     /**
79      * @return the allowed maximum size of the encoded line.
80      * If the size of the encoded line exceeds this value, the encoder
81      * will throw a {@link IllegalArgumentException}.  The default value
82      * is {@link Integer#MAX_VALUE}.
83      */
84     int getMaxLineLength() {
85         return maxLineLength;
86     }
87 
88     /**
89      * Sets the allowed maximum size of the encoded line.
90      * If the size of the encoded line exceeds this value, the encoder
91      * will throw a {@link IllegalArgumentException}.  The default value
92      * is {@link Integer#MAX_VALUE}.
93      * 
94      * @param maxLineLength The maximum line length
95      */
96     void setMaxLineLength(int maxLineLength) {
97         if (maxLineLength <= 0) {
98             throw new IllegalArgumentException("maxLineLength: " ~ maxLineLength.to!string());
99         }
100 
101         this.maxLineLength = maxLineLength;
102     }
103 
104     /**
105      * {@inheritDoc}
106      */
107     override
108     void encode(Object message, Connection connection) {
109 
110         string delimiterValue = delimiter.getValue();
111 
112         string value = message is null ? "" : message.toString();
113         ByteBuffer buf = BufferUtils.allocate(cast(int)(value.length+delimiterValue.length));
114         buf.put(value);
115 
116         if (buf.position() > maxLineLength) {
117             throw new IllegalArgumentException("Line length: " ~ buf.position().to!string());
118         }
119 
120         buf.put(delimiterValue);
121         buf.flip();
122 
123         connection.write(buf);
124     }
125 
126     /**
127      * Dispose the encoder
128      * 
129      * @throws Exception If the dispose failed
130      */
131     void dispose()  {
132         // Do nothing
133     }
134 }