// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_CONTINUATION_FRAME = 0x09;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_DATA_FRAME = 0x00;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_DEFAULT_DEPENDENCY = 0;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_DEFAULT_WEIGHT = 16;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_ACK = 0x01;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_END_HEADERS = 0x04;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_END_STREAM = 0x01;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_PRIORITY = 0x20;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_FRAME_HEADER_SIZE = 9;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_GOAWAY_FRAME = 0x07;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_HEADERS_FRAME = 0x01;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_MAX_LENGTH = 0x4000; // Initial MAX_FRAME_SIZE value is 2^14
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_PING_FRAME = 0x06;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_PRIORITY_FRAME = 0x02;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_PUSH_PROMISE_FRAME = 0x05;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_RST_STREAM_FRAME = 0x03;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_SETTINGS_FRAME = 0x04;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_WINDOW_UPDATE_FRAME = 0x08;


import java.util.Set;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import static com.twitter.http2.HttpCodecUtil.HTTP_CONTINUATION_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_DATA_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_DEFAULT_DEPENDENCY;
import static com.twitter.http2.HttpCodecUtil.HTTP_DEFAULT_WEIGHT;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_ACK;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_END_HEADERS;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_END_STREAM;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_PRIORITY;
import static com.twitter.http2.HttpCodecUtil.HTTP_FRAME_HEADER_SIZE;
import static com.twitter.http2.HttpCodecUtil.HTTP_GOAWAY_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_HEADERS_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_MAX_LENGTH;
import static com.twitter.http2.HttpCodecUtil.HTTP_PING_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_PRIORITY_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_PUSH_PROMISE_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_RST_STREAM_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_SETTINGS_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_WINDOW_UPDATE_FRAME;
/*
 * Copyright 2015 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.twitter.http2;




/**
 * Encodes an HTTP/2 Frame into a {@link ByteBuf}.
 */
public class HttpFrameEncoder {

    /**
     * Encode an HTTP/2 DATA Frame
     */
    public ByteBuf encodeDataFrame(int streamId, boolean endStream, ByteBuf data) {
        byte flags = endStream ? HTTP_FLAG_END_STREAM : 0;
        ByteBuf header = Unpooled.buffer(HTTP_FRAME_HEADER_SIZE);
        writeFrameHeader(header, data.readableBytes(), HTTP_DATA_FRAME, flags, streamId);
        return Unpooled.wrappedBuffer(header, data);
    }

    /**
     * Encode an HTTP/2 HEADERS Frame
     */
    public ByteBuf encodeHeadersFrame(
            int streamId,
            boolean endStream,
            boolean exclusive,
            int dependency,
            int weight,
            ByteBuf headerBlock
    ) {
        byte flags = endStream ? HTTP_FLAG_END_STREAM : 0;
        boolean hasPriority = exclusive
                || dependency != HTTP_DEFAULT_DEPENDENCY || weight != HTTP_DEFAULT_WEIGHT;
        if (hasPriority) {
            flags |= HTTP_FLAG_PRIORITY;
        }
        int maxLength = hasPriority ? HTTP_MAX_LENGTH - 5 : HTTP_MAX_LENGTH;
        boolean needsContinuations = headerBlock.readableBytes() > maxLength;
        if (!needsContinuations) {
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_CONTINUATION_FRAME = 0x09;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_DATA_FRAME = 0x00;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_DEFAULT_DEPENDENCY = 0;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_DEFAULT_WEIGHT = 16;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_ACK = 0x01;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_END_HEADERS = 0x04;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_END_STREAM = 0x01;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final byte HTTP_FLAG_PRIORITY = 0x20;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_FRAME_HEADER_SIZE = 9;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_GOAWAY_FRAME = 0x07;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_HEADERS_FRAME = 0x01;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_MAX_LENGTH = 0x4000; // Initial MAX_FRAME_SIZE value is 2^14
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_PING_FRAME = 0x06;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_PRIORITY_FRAME = 0x02;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_PUSH_PROMISE_FRAME = 0x05;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_RST_STREAM_FRAME = 0x03;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_SETTINGS_FRAME = 0x04;
// 
// Path: src/main/java/com/twitter/http2/HttpCodecUtil.java
// static final int HTTP_WINDOW_UPDATE_FRAME = 0x08;


// Path: src/main/java/com/twitter/http2/HttpFrameEncoder.java
import java.util.Set;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import static com.twitter.http2.HttpCodecUtil.HTTP_CONTINUATION_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_DATA_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_DEFAULT_DEPENDENCY;
import static com.twitter.http2.HttpCodecUtil.HTTP_DEFAULT_WEIGHT;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_ACK;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_END_HEADERS;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_END_STREAM;
import static com.twitter.http2.HttpCodecUtil.HTTP_FLAG_PRIORITY;
import static com.twitter.http2.HttpCodecUtil.HTTP_FRAME_HEADER_SIZE;
import static com.twitter.http2.HttpCodecUtil.HTTP_GOAWAY_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_HEADERS_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_MAX_LENGTH;
import static com.twitter.http2.HttpCodecUtil.HTTP_PING_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_PRIORITY_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_PUSH_PROMISE_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_RST_STREAM_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_SETTINGS_FRAME;
import static com.twitter.http2.HttpCodecUtil.HTTP_WINDOW_UPDATE_FRAME;

/*
 * Copyright 2015 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.twitter.http2;




/**
 * Encodes an HTTP/2 Frame into a {@link ByteBuf}.
 */
public class HttpFrameEncoder {

    /**
     * Encode an HTTP/2 DATA Frame
     */
    public ByteBuf encodeDataFrame(int streamId, boolean endStream, ByteBuf data) {
        byte flags = endStream ? HTTP_FLAG_END_STREAM : 0;
        ByteBuf header = Unpooled.buffer(HTTP_FRAME_HEADER_SIZE);
        writeFrameHeader(header, data.readableBytes(), HTTP_DATA_FRAME, flags, streamId);
        return Unpooled.wrappedBuffer(header, data);
    }

    /**
     * Encode an HTTP/2 HEADERS Frame
     */
    public ByteBuf encodeHeadersFrame(
            int streamId,
            boolean endStream,
            boolean exclusive,
            int dependency,
            int weight,
            ByteBuf headerBlock
    ) {
        byte flags = endStream ? HTTP_FLAG_END_STREAM : 0;
        boolean hasPriority = exclusive
                || dependency != HTTP_DEFAULT_DEPENDENCY || weight != HTTP_DEFAULT_WEIGHT;
        if (hasPriority) {
            flags |= HTTP_FLAG_PRIORITY;
        }
        int maxLength = hasPriority ? HTTP_MAX_LENGTH - 5 : HTTP_MAX_LENGTH;
        boolean needsContinuations = headerBlock.readableBytes() > maxLength;
        if (!needsContinuations) {
            flags |= HTTP_FLAG_END_HEADERS;