blob: 0cc102ba264bc4b8fa6353b8a0e18fc359e6a9fa [file] [log] [blame]
Carmelo Cascone17fc9e42016-05-31 11:29:21 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.bmv2.api.utils;
18
Carmelo Cascone9e39e312016-06-16 14:47:09 -070019import com.google.common.annotations.Beta;
Carmelo Cascone17fc9e42016-05-31 11:29:21 -070020import org.onlab.util.HexString;
21import org.onlab.util.ImmutableByteSequence;
22
23import java.util.Arrays;
24
25import static com.google.common.base.Preconditions.checkArgument;
26import static com.google.common.base.Preconditions.checkNotNull;
27
28/**
Carmelo Cascone9e39e312016-06-16 14:47:09 -070029 * Collection of utility methods to deal with flow rule translation.
Carmelo Cascone17fc9e42016-05-31 11:29:21 -070030 */
Carmelo Cascone9e39e312016-06-16 14:47:09 -070031@Beta
Carmelo Cascone17fc9e42016-05-31 11:29:21 -070032public final class Bmv2TranslatorUtils {
33
34 private Bmv2TranslatorUtils() {
35 // Ban constructor.
36 }
37
38 /**
39 * Returns the number of bytes necessary to contain the given bit-width.
40 *
41 * @param bitWidth an integer value
42 * @return an integer value
43 */
44 public static int roundToBytes(int bitWidth) {
45 return (int) Math.ceil((double) bitWidth / 8);
46 }
47
48 /**
49 * Trims or expands the given byte sequence so to fit a given bit-width.
50 *
51 * @param original a byte sequence
52 * @param bitWidth an integer value
53 * @return a new byte sequence
54 * @throws ByteSequenceFitException if the byte sequence cannot be fitted in the given bit-width
55 */
56 public static ImmutableByteSequence fitByteSequence(ImmutableByteSequence original, int bitWidth)
57 throws ByteSequenceFitException {
58
59 checkNotNull(original, "byte sequence cannot be null");
60 checkArgument(bitWidth > 0, "byte width must a non-zero positive integer");
61
62 int newByteWidth = roundToBytes(bitWidth);
63
64 if (original.size() == newByteWidth) {
65 // nothing to do
66 return original;
67 }
68
69 byte[] originalBytes = original.asArray();
70
71 if (newByteWidth > original.size()) {
72 // pad missing bytes with zeros
73 return ImmutableByteSequence.copyFrom(Arrays.copyOf(originalBytes, newByteWidth));
74 }
75
76 byte[] newBytes = new byte[newByteWidth];
77 // ImmutableByteSequence is always big-endian, hence check the array in reverse order
78 int diff = originalBytes.length - newByteWidth;
79 for (int i = originalBytes.length - 1; i > 0; i--) {
80 byte ob = originalBytes[i]; // original byte
81 byte nb; // new byte
82 if (i > diff) {
83 // no need to truncate, copy as is
84 nb = ob;
85 } else if (i == diff) {
86 // truncate this byte, check if we're loosing something
87 byte mask = (byte) ((1 >> ((bitWidth % 8) + 1)) - 1);
88 if ((ob & ~mask) != 0) {
89 throw new ByteSequenceFitException(originalBytes, bitWidth);
90 } else {
91 nb = (byte) (ob & mask);
92 }
93 } else {
94 // drop this byte, check if we're loosing something
95 if (originalBytes[i] != 0) {
96 throw new ByteSequenceFitException(originalBytes, bitWidth);
97 } else {
98 continue;
99 }
100 }
101 newBytes[i - diff] = nb;
102 }
103
104 return ImmutableByteSequence.copyFrom(newBytes);
105 }
106
107 /**
108 * A byte sequence fit exception.
109 */
110 public static class ByteSequenceFitException extends Exception {
111 public ByteSequenceFitException(byte[] bytes, int bitWidth) {
112 super("cannot fit " + HexString.toHexString(bytes) + " into a " + bitWidth + " bits value");
113 }
114 }
115}