text:
// Ops for operating with sets. They are not checked in
// to TensorFlow because we would first like to demonstrate successful
// end-to-end use of these ops in eval and polush the api a bit like taking two
// SparseTensor rather than on edense and one sparse.

#define EIGEN_USE_THREADS

#include <algorithm>
#include <numeric>
// TODO(ptucker): Consider switching back to hash_set - I had trouble getting it
// to work with string values.
#include <set>
#include <string>

#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_util.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/util/sparse/sparse_tensor.h"

namespace tensorflow {

using ShapeArray = sparse::SparseTensor::ShapeArray;
using VarDimArray = sparse::SparseTensor::VarDimArray;

// Validate rank >= 2.
void CheckRankAtLeast2(OpKernelContext* ctx, const TensorShape& shape) {
  const auto rank = shape.dims();
  OP_REQUIRES(ctx, rank >= 2,
              errors::InvalidArgument("Invalid rank ", rank, "."));
}

// Return group shape, which is the 1st n-1 dimensions of shape.
Status GroupShape(const VarDimArray& input_shape, ShapeArray* grouped_shape) {
  if (input_shape.size() < 2) {
    // TODO(irving): Why can't 2 be 1 here?
    return errors::InvalidArgument("Shape [", str_util::Join(input_shape, ","),
                                   "] has rank ", input_shape.size(), " < 2");
  }
  // grouped_shape is input_shape[:-1]
  *grouped_shape = ShapeArray(input_shape.begin(), input_shape.end() - 1);
  return Status::OK();
}

// Build `SparseTensor` from indices, values, and shape in inputs
// [base_index, base_index + 3), and validate its rank and indices.
Status SparseTensorFromContext(OpKernelContext* ctx, const int32 base_index,
                               bool validate_indices,
                               sparse::SparseTensor* tensor) {
  // Assume row-major order.
  const TensorShape shape =
      TensorShape(ctx->input(base_index + 2).vec<int64>());
  CheckRankAtLeast2(ctx, shape);
  std::vector<int64> order(shape.dims());
  std::iota(order.begin(), order.end(), 0);

  return sparse::SparseTensor::Create(
      ctx->input(base_index), ctx->input(base_index + 1), shape, order, tensor);
}

// TODO(ptucker): CheckGroup is just a sanity check on the result of
// SparseTensor.group, consider removing.
// `sparse_tensor_shape` is the shape of the `SparseTensor` from which group
// was created, and is used to sanity check the indices in `group'.
template <typename T>
void CheckGroup(OpKernelContext* ctx, const sparse::Group& group,
                const VarDimArray& sparse_tensor_shape) {
  const auto& indices = group.indices();
  const auto& values = group.values<T>();

  // Sanity check: group is non-empty, and indices and values are same size.
  const auto num_values = values.dimension(0);
  OP_REQUIRES(ctx, indices.size() > 0, errors::Internal("Empty group."));
  OP_REQUIRES(
      ctx, indices.dimension(0) == num_values,
      errors::Internal("shape[0] of group indices ", indices.dimension(0),
                       " != values ", num_values, "."));

  // Sanity check: valid indices.
  const auto group_rank = indices.dimension(1);
  const auto expected_rank = sparse_tensor_shape.size();
  OP_REQUIRES(ctx, expected_rank == group_rank,
              errors::Internal("Rank expected ", expected_rank, ", got ",
                               group_rank, "."));
  for (int32 j = 0; j < expected_rank; ++j) {
    const auto dim_size = sparse_tensor_shape[j];
    OP_REQUIRES(
        ctx, dim_size > 0,
        errors::Internal("Invalid dim_size[", j, "] = ", dim_size, "."));
    for (int64 i = 0; i < num_values; ++i) {
      const auto index = indices(i, j);
      OP_REQUIRES(ctx, dim_size > index,
                  errors::Internal("indices[", i, ", ", j, "] expected < ",
                                   dim_size, ", got ", index, "."));
    }
  }
}

// This lets us calculate the row-major index into flattened output.
const ShapeArray Strides(const VarDimArray& shape) {
  ShapeArray result(shape.size());
  int64 product = 1;
  for (int i = shape.size() - 1; i >= 0; --i) {
    result[i] = product;
    product *= shape[i];
  }
  return result;
}

// TODO(ptucker): If memory becomes an issue, consider a 2-pass approach to
// eliminate the intermediate `values` data structure - iterate once to
// determine `num_values`, allocate output tensors, then write results directly
// to output tensors.

// TODO(ptucker): Consider sharding work across multiple threads. See
// SparseCrossOp for an example.

// Output `SparseTensor` of shape `output_shape`. `sets` contains a map of
// group indices (i.e., values for all but the last dimension of `output_shape`)
// to set values, each of which will occupy the last dimension of
// `output_shape`.
template <typename T>
void OutputSparseTensor(OpKernelContext* ctx, const TensorShape& output_shape,
                        const int64 num_values,
                        const std::map<std::vector<int64>, std::set<T>>& sets) {
  // Allocate 3 output tensors for sparse data.
  Tensor *out_indices_t, *out_values_t, *out_shape_t;
  OP_REQUIRES_OK(ctx, ctx->allocate_output(
                          0, TensorShape({num_values, output_shape.dims()}),
                          &out_indices_t));
  OP_REQUIRES_OK(
      ctx, ctx->allocate_output(1, TensorShape({num_values}), &out_values_t));
  OP_REQUIRES_OK(ctx, ctx->allocate_output(
                          2, TensorShape({output_shape.dims()}), &out_shape_t));
  auto out_indices_mat = out_indices_t->matrix<int64>();
  auto out_values_flat = out_values_t->vec<T>();

  // For each set, write its indices and values to output tensors.
  int64 value_index = 0;
  for (auto it = sets.begin(); it != sets.end(); ++it) {
    const auto& group_indices = it->first;
    OP_REQUIRES(
        ctx, group_indices.size() == output_shape.dims() - 1,
        errors::Internal("Invalid number of indices ", group_indices.size(),
                         ", expected ", output_shape.dims() - 1, "."));
    const auto& set = it->second;

    // For each set item, write its indices and value to output tensors.
    int64 group_value_index = 0;
    for (auto value = set.begin(); value != set.end();
         ++value, ++value_index, ++group_value_index) {
      // First n-1 dimensions are the group, last dimension is the position in
      // the set.
      for (int32 i = 0; i < group_indices.size(); ++i) {
        out_indices_mat(value_index, i) = group_indices[i];
      }
      out_indices_mat(value_index, group_indices.size()) = group_value_index;

      out_values_flat(value_index) = *value;
    }
  }

  // Write output shape.
  auto out_shape_flat = out_shape_t->vec<int64>();
  for (int32 i = 0; i < output_shape.dims(); ++i) {
    out_shape_flat(i) = output_shape.dim_size(i);
  }
}

bool ValidateIndicesFromContext(OpKernelConstruction* ctx) {
  bool result;
  if (ctx->GetAttr("validate_indices", &result).ok()) {
    return result;
  }
  return true;
}

// Populate `result` set from group in `tensor`. "Group" is defined by
// `group_indices`, which are values for the first n-1 dimensions of
// `input_tensor`. `input_strides` is provided to avoid recalculating it
// multiple times, and is used to calculate the flat index into `input_tensor`
// values.
template <typename T>
void PopulateFromDenseGroup(OpKernelContext* ctx, const Tensor& input_tensor,
                            const VarDimArray& input_strides,
                            const std::vector<int64>& group_indices,
                            std::set<T>* result) {
  OP_REQUIRES(ctx, group_indices.size() == input_strides.size() - 1,
              errors::Internal("group_indices.size ", group_indices.size(),
                               ", !=  input_strides.size-1 ",
                               input_strides.size() - 1, "."));
  result->clear();
  auto input_flat = input_tensor.flat<T>();
  const auto start = std::inner_product(
      group_indices.begin(), group_indices.end(), input_strides.begin(), 0LL);
  const TensorShape& input_shape = input_tensor.shape();
  const auto end = start + input_shape.dim_size(input_shape.dims() - 1);
  for (int64 i = start; i < end; ++i) {
    result->insert(input_flat(i));
  }
}

// Populate `result` set from `group`. `sparse_tensor_shape` is the shape of the
// `SparseTensor` from which group was created, and is used to sanity check the
// indices in `group'.
template <typename T>
void PopulateFromSparseGroup(OpKernelContext* ctx, const sparse::Group& group,
                             const VarDimArray& sparse_tensor_shape,
                             std::set<T>* result) {
  CheckGroup<T>(ctx, group, sparse_tensor_shape);
  result->clear();
  const auto& group_values = group.values<T>();
  for (int64 i = 0; i < group_values.size(); ++i) {
    result->insert(group_values(i));
  }
}

template <typename T>
class SetSizeOp : public OpKernel {
 public:
  explicit SetSizeOp(OpKernelConstruction* ctx)
      : OpKernel(ctx), validate_indices_(ValidateIndicesFromContext(ctx)) {}

  void Compute(OpKernelContext* ctx) override;

 private:
  const bool validate_indices_;
};

template <typename T>
void SetSizeOp<T>::Compute(OpKernelContext* ctx) {
  sparse::SparseTensor set_st;
  OP_REQUIRES_OK(ctx,
                 SparseTensorFromContext(ctx, 0, validate_indices_, &set_st));
  OP_REQUIRES_OK(ctx, set_st.IndicesValid());

  // Output shape is same as input except for last dimension, which reduces
  // to the set size of values along that dimension.
  ShapeArray output_shape;
  OP_REQUIRES_OK(ctx, GroupShape(set_st.shape(), &output_shape));
  const auto output_strides = Strides(output_shape);

  TensorShape output_shape_ts;
  OP_REQUIRES_OK(ctx,
                 TensorShapeUtils::MakeShape(output_shape, &output_shape_ts));
  Tensor* out_t;
  OP_REQUIRES_OK(ctx, ctx->allocate_output(0, output_shape_ts, &out_t));
  auto out = out_t->flat<int32>();
  out.device(ctx->eigen_cpu_device()) = out.constant(static_cast<int32>(0.0));

  // Group by all but last dimension, create a set of group values, and add set
  // size to output.
  VarDimArray group_ix = set_st.order().subspan(0, set_st.order().size() - 1);
  std::set<T> group_set;
  for (const auto& group : set_st.group(group_ix)) {
    PopulateFromSparseGroup<T>(ctx, group, set_st.shape(), &group_set);

    const auto group_key = group.group();
    const auto output_index = std::inner_product(
        group_key.begin(), group_key.end(), output_strides.begin(), 0LL);
    out(output_index) = group_set.size();
  }
}

#define _SET_SIZE_REGISTER_KERNEL_BUILDER(T)                     \
  REGISTER_KERNEL_BUILDER(                                       \
      Name("SetSize").Device(DEVICE_CPU).TypeConstraint<T>("T"), \
      SetSizeOp<T>);
_SET_SIZE_REGISTER_KERNEL_BUILDER(int8);
_SET_SIZE_REGISTER_KERNEL_BUILDER(int16);
_SET_SIZE_REGISTER_KERNEL_BUILDER(int32);
_SET_SIZE_REGISTER_KERNEL_BUILDER(int64);
_SET_SIZE_REGISTER_KERNEL_BUILDER(uint8);
_SET_SIZE_REGISTER_KERNEL_BUILDER(uint16);
_SET_SIZE_REGISTER_KERNEL_BUILDER(string);
#undef _SET_SIZE_REGISTER_KERNEL_BUILDER

enum InputTypes {
  DENSE_DENSE = 0,
  DENSE_SPARSE = 1,
  SPARSE_SPARSE = 2,
};

enum SetOperation { A_MINUS_B = 0, B_MINUS_A = 1, INTERSECTION = 2, UNION = 3 };

SetOperation SetOperationFromContext(OpKernelConstruction* ctx) {
  string set_operation_str;
  if (!ctx->GetAttr("set_operation", &set_operation_str).ok()) {
    ctx->CtxFailure(errors::InvalidArgument("Missing set_operation."));
  } else {
    std::transform(set_operation_str.begin(), set_operation_str.end(),
                   set_operation_str.begin(), ::tolower);
    if ("a-b" == set_operation_str) {
      return A_MINUS_B;
    }
    if ("b-a" == set_operation_str) {
      return B_MINUS_A;
    }
    if ("intersection" == set_operation_str) {
      return INTERSECTION;
    }
    if ("union" != set_operation_str) {
      ctx->CtxFailure(errors::InvalidArgument("Invalid set_operation ",
                                              set_operation_str, "."));
    }
  }
  // NOTE: This is not the default, this function fails if no 'set_operation'
  // attribute is provided.
  return UNION;
}

// Abstract base class for performing set operations across the last dimension
// of 2 input tensors.
template <typename T>
class SetOperationOp : public OpKernel {
 public:
  SetOperationOp(OpKernelConstruction* ctx, InputTypes input_types)
      : OpKernel(ctx),
        set_operation_(SetOperationFromContext(ctx)),
        validate_indices_(ValidateIndicesFromContext(ctx)),
        input_types_(input_types) {}

  void Compute(OpKernelContext* ctx) override;

 private:
  void ApplySetOperation(const std::set<T>& set1, const std::set<T>& set2,
                         std::set<T>* result) const;
  void ComputeDenseToDense(OpKernelContext* ctx) const;
  void ComputeDenseToSparse(OpKernelContext* ctx) const;
  void ComputeSparseToSparse(OpKernelContext* ctx) const;
  const SetOperation set_operation_;
  const bool validate_indices_;
  const InputTypes input_types_;
};

template <typename T>
void SetOperationOp<T>::ApplySetOperation(const std::set<T>& set1,
                                          const std::set<T>& set2,
                                          std::set<T>* result) const {
  switch (set_operation_) {
    case A_MINUS_B:
      std::set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(),
                          std::inserter(*result, result->begin()));
      break;
    case B_MINUS_A:
      std::set_difference(set2.begin(), set2.end(), set1.begin(), set1.end(),
                          std::inserter(*result, result->begin()));
      break;
    case INTERSECTION:
      std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(),
                            std::inserter(*result, result->begin()));
      break;
    case UNION:
      std::set_union(set1.begin(), set1.end(), set2.begin(), set2.end(),
                     std::inserter(*result, result->begin()));
      break;
  }
}

// Validate shapes have the same dimensions.
Status CheckShapesMatch(VarDimArray shape1, VarDimArray shape2) {
  if (shape1 != shape2) {
    return errors::InvalidArgument("Mismatched shapes [",
                                   str_util::Join(shape1, ","), "] vs [",
                                   str_util::Join(shape2, ","), "]");
  }
  return Status::OK();
}

// Validate ranks are the same, and all but last dimension are the same.
// Return GroupShape.
Status GroupShapeFromInputs(VarDimArray shape1, VarDimArray shape2,
                            ShapeArray* group_shape) {
  ShapeArray group_shape_1;
  TF_RETURN_IF_ERROR(GroupShape(shape1, &group_shape_1));
  ShapeArray group_shape_2;
  TF_RETURN_IF_ERROR(GroupShape(shape2, &group_shape_2));
  TF_RETURN_IF_ERROR(CheckShapesMatch(group_shape_1, group_shape_2));
  *group_shape = group_shape_1;
  return Status::OK();
}

// Split `flat_group_index` into separate dimensions based on `group_shape`.
void PopulateGroupIndices(const int64 flat_group_index, VarDimArray group_shape,
                          std::vector<int64>* group_indices) {
  group_indices->clear();
  int64 running_flat_group_index = flat_group_index;
  for (int group_dim_index = group_shape.size() - 1; group_dim_index >= 0;
       --group_dim_index) {
    const auto group_dim = group_shape[group_dim_index];
    group_indices->insert(group_indices->begin(),
                          running_flat_group_index % group_dim);
    running_flat_group_index /= group_dim;
  }
}

ShapeArray TensorShapeToArray(const TensorShape& t) {
  ShapeArray vec(t.dims());
  for (int i = 0; i < t.dims(); ++i) vec[i] = t.dim_size(i);
  return vec;
};

// `ctx` contains set1 and set2 dense tensors.
// Iterate over groups in set1 and set2, applying `ApplySetOperation` to each,
// and outputing the result `SparseTensor`. A "group" is a collection of values
// with the same first n-1 dimensions in set1 and set2.
template <typename T>
void SetOperationOp<T>::ComputeDenseToDense(OpKernelContext* ctx) const {
  const Tensor& set1_t = ctx->input(0);
  const Tensor& set2_t = ctx->input(1);
  // The following should stay in sync with `_dense_to_dense_shape` shape
  // assertions in python/ops/set_ops.py, and `SetShapeFn` for
  // `DenseToDenseSetOperation` in ops/set_ops.cc.
  ShapeArray group_shape;
  const auto shape1 = TensorShapeToArray(set1_t.shape());
  const auto shape2 = TensorShapeToArray(set2_t.shape());
  OP_REQUIRES_OK(ctx, GroupShapeFromInputs(shape1, shape2, &group_shape));

  const auto set1_strides = Strides(shape1);
  const auto set2_strides = Strides(shape2);

  std::map<std::vector<int64>, std::set<T>> group_sets;
  int64 num_result_values = 0;
  int64 max_set_size = 0;

  std::set<T> set1_group_set;
  std::set<T> set2_group_set;
  std::vector<int64> group_indices;
  int64 num_elements;
  OP_REQUIRES_OK(ctx,
                 TensorShapeUtils::NumElements(group_shape, &num_elements));
  for (int64 flat_group_index = 0; flat_group_index < num_elements;
       ++flat_group_index) {
    PopulateGroupIndices(flat_group_index, group_shape, &group_indices);
    PopulateFromDenseGroup<T>(ctx, set1_t, set1_strides, group_indices,
                              &set1_group_set);
    PopulateFromDenseGroup<T>(ctx, set2_t, set2_strides, group_indices,
                              &set2_group_set);

    std::set<T> group_set;
    ApplySetOperation(set1_group_set, set2_group_set, &group_set);
    if (!group_set.empty()) {
      group_sets[group_indices] = group_set;
      const auto set_size = group_set.size();
      if (set_size > max_set_size) {
        max_set_size = set_size;
      }
      num_result_values += set_size;
    }
  }

  TensorShape output_shape;
  OP_REQUIRES_OK(ctx, TensorShapeUtils::MakeShape(group_shape, &output_shape));
  output_shape.AddDim(max_set_size);
  OutputSparseTensor<T>(ctx, output_shape, num_result_values, group_sets);
}

// `ctx` contains dense set1 and sparse set2 tensors.
// Iterate over groups in set1 and set2, applying `ApplySetOperation` to each,
// and outputing the result `SparseTensor`. A "group" is a collection of values
// with the same first n-1 dimensions in set1 and set2.
template <typename T>
void SetOperationOp<T>::ComputeDenseToSparse(OpKernelContext* ctx) const {
  const Tensor& set1_t = ctx->input(0);
  sparse::SparseTensor set2_st;
  OP_REQUIRES_OK(ctx,
                 SparseTensorFromContext(ctx, 1, validate_indices_, &set2_st));
  OP_REQUIRES_OK(ctx, set2_st.IndicesValid());
  // The following should stay in sync with `_dense_to_sparse_shape` shape
  // assertions in python/ops/set_ops.py, and `SetShapeFn` for
  // `DenseToSparseSetOperation` in ops/set_ops.cc.
  ShapeArray group_shape;
  OP_REQUIRES_OK(ctx, GroupShapeFromInputs(TensorShapeToArray(set1_t.shape()),
                                           set2_st.shape(), &group_shape));

  const ShapeArray set1_strides = Strides(TensorShapeToArray(set1_t.shape()));

  std::map<std::vector<int64>, std::set<T>> group_sets;
  int64 num_result_values = 0;
  int64 max_set_size = 0;

  std::set<T> set1_group_set;
  std::set<T> set2_group_set;
  auto set2_grouper =
      set2_st.group(set2_st.order().subspan(0, set2_st.order().size() - 1));
  auto set2_group_it = set2_grouper.begin();
  std::vector<int64> group_indices;
  int64 num_elements;
  OP_REQUIRES_OK(ctx,
                 TensorShapeUtils::NumElements(group_shape, &num_elements));
  for (int64 flat_group_index = 0; flat_group_index < num_elements;
       ++flat_group_index) {
    PopulateGroupIndices(flat_group_index, group_shape, &group_indices);

    // Get values from set1.
    PopulateFromDenseGroup<T>(ctx, set1_t, set1_strides, group_indices,
                              &set1_group_set);

    // Get values from set2, if applicable.
    set2_group_set.clear();
    if (set2_group_it != set2_grouper.end()) {
      const auto& group = *set2_group_it;
      const auto set2_group_indices = group.group();
      OP_REQUIRES(
          ctx, set2_group_indices.size() == group_indices.size(),
          errors::InvalidArgument("Invalid number of group indices ",
                                  set2_group_indices.size(), ", expected ",
                                  group_indices.size(), "."));
      bool group_match = true;
      for (int32 i = 0; group_match && (i < set2_group_indices.size()); ++i) {
        if (set2_group_indices[i] != group_indices[i]) {
          group_match = false;
        }
      }
      if (group_match) {
        PopulateFromSparseGroup<T>(ctx, group, set2_st.shape(),
                                   &set2_group_set);
        ++set2_group_it;
      }
    }

    std::set<T> group_set;
    ApplySetOperation(set1_group_set, set2_group_set, &group_set);
    if (!group_set.empty()) {
      group_sets[group_indices] = group_set;
      const auto set_size = group_set.size();
      if (set_size > max_set_size) {
        max_set_size = set_size;
      }
      num_result_values += set_size;
    }
  }

  TensorShape output_shape;
  OP_REQUIRES_OK(ctx, TensorShapeUtils::MakeShape(group_shape, &output_shape));
  output_shape.AddDim(max_set_size);
  OutputSparseTensor<T>(ctx, output_shape, num_result_values, group_sets);
}

// This is used to determine which group iterator is less than the other, based
// on row-major ordering of indices.
// An empty index list indicates end of iteration, which is interpreted as "max"
// for the purposes of comparison; i.e., non-empty < empty.
// Return 0 if both groups are empty, or both non-empty with the same values.
// Return <0 if set1 <= set2, or set2 is empty.
// Return >0 if set2 <= set1, or set1 is empty.
void CompareGroups(OpKernelContext* ctx,
                   const std::vector<int64>& set1_group_indices,
                   const std::vector<int64>& set2_group_indices,
                   int64* result) {
  if (set1_group_indices.empty()) {
    *result = set2_group_indices.empty() ? 0 : 1;
    return;
  }
  if (set2_group_indices.empty()) {
    *result = set1_group_indices.empty() ? 0 : -1;
    return;
  }
  OP_REQUIRES(ctx, set1_group_indices.size() == set2_group_indices.size(),
              errors::InvalidArgument("Mismatched group dims ",
                                      set1_group_indices.size(), " vs ",
                                      set2_group_indices.size(), "."));
  for (int32 i = 0; i < set1_group_indices.size(); ++i) {
    *result = set1_group_indices[i] - set2_group_indices[i];
    if (*result != 0) {
      return;
    }
  }
}

// Empty indices vector represents iteration end in `CompareGroups`.
const std::vector<int64> GROUP_ITER_END;

// `ctx` contains set1 and set2 sparse tensors.
// Iterate over groups in set1 and set2, applying `ApplySetOperation` to each,
// and outputing the result `SparseTensor`. A "group" is a collection of values
// with the same first n-1 dimensions in set1 and set2.
template <typename T>
void SetOperationOp<T>::ComputeSparseToSparse(OpKernelContext* ctx) const {
  sparse::SparseTensor set1_st;
  OP_REQUIRES_OK(ctx,
                 SparseTensorFromContext(ctx, 0, validate_indices_, &set1_st));
  OP_REQUIRES_OK(ctx, set1_st.IndicesValid());

  sparse::SparseTensor set2_st;
  OP_REQUIRES_OK(ctx,
                 SparseTensorFromContext(ctx, 3, validate_indices_, &set2_st));

  // The following should stay in sync with `_sparse_to_sparse_shape` shape
  // assertions in python/ops/set_ops.py, and `SetShapeFn` for
  // `SparseToSparseSetOperation` in ops/set_ops.cc.
  ShapeArray group_shape;
  OP_REQUIRES_OK(ctx, GroupShapeFromInputs(set1_st.shape(), set2_st.shape(),
                                           &group_shape));

  const ShapeArray set1_strides = Strides(set1_st.shape());
  const ShapeArray set2_strides = Strides(set2_st.shape());

  std::map<std::vector<int64>, std::set<T>> group_sets;
  int64 num_result_values = 0;
  int64 max_set_size = 0;

  std::set<T> set1_group_set;
  std::set<T> set2_group_set;
  auto set1_grouper =
      set1_st.group(set1_st.order().subspan(0, set1_st.order().size() - 1));
  auto set1_group_it = set1_grouper.begin();
  auto set2_grouper =
      set2_st.group(set2_st.order().subspan(0, set2_st.order().size() - 1));
  auto set2_group_it = set2_grouper.begin();

  // Group by rows, and iterate over rows of both sets in parallel, creating a
  // set for each row.
  while ((set1_group_it != set1_grouper.end()) ||
         (set2_group_it != set2_grouper.end())) {
    const std::vector<int64>& set1_group_indices =
        (set1_group_it == set1_grouper.end()) ? GROUP_ITER_END
                                              : (*set1_group_it).group();
    const std::vector<int64>& set2_group_indices =
        (set2_group_it == set2_grouper.end()) ? GROUP_ITER_END
                                              : (*set2_group_it).group();

    int64 compare_groups;
    CompareGroups(ctx, set1_group_indices, set2_group_indices, &compare_groups);
    const std::vector<int64>* group_indices = nullptr;

    // Get values from set1, if applicable.
    set1_group_set.clear();
    if (compare_groups <= 0) {
      PopulateFromSparseGroup<T>(ctx, *set1_group_it, set1_st.shape(),
                                 &set1_group_set);
      ++set1_group_it;
      group_indices = &set1_group_indices;
    }

    // Get values from set2, if applicable.
    set2_group_set.clear();
    if (compare_groups >= 0) {
      PopulateFromSparseGroup<T>(ctx, *set2_group_it, set2_st.shape(),
                                 &set2_group_set);
      ++set2_group_it;
      group_indices = &set2_group_indices;
    }

    std::set<T> group_set;
    ApplySetOperation(set1_group_set, set2_group_set, &group_set);
    if (!group_set.empty()) {
      group_sets[*group_indices] = group_set;
      const auto set_size = group_set.size();
      if (set_size > max_set_size) {
        max_set_size = set_size;
      }
      num_result_values += set_size;
    }
  }

  TensorShape output_shape;
  OP_REQUIRES_OK(ctx, TensorShapeUtils::MakeShape(group_shape, &output_shape));
  output_shape.AddDim(max_set_size);
  OutputSparseTensor<T>(ctx, output_shape, num_result_values, group_sets);
}

// Given set1 of shape [b, n1] and data_2 of shape [b, n2], populate result
// sparse tendor with [b, n3] values, where each row `i` contains the result of
// the set operation on elements from set1[i] and set2[i]. `n3` is the number
// of elements in that result row.
template <typename T>
void SetOperationOp<T>::Compute(OpKernelContext* ctx) {
  switch (input_types_) {
    case DENSE_DENSE:
      ComputeDenseToDense(ctx);
      break;
    case DENSE_SPARSE:
      ComputeDenseToSparse(ctx);
      break;
    case SPARSE_SPARSE:
      ComputeSparseToSparse(ctx);
      break;
  }
}

template <typename T>
class DenseToDenseSetOperationOp : public SetOperationOp<T> {
 public:
  explicit DenseToDenseSetOperationOp(OpKernelConstruction* ctx)
      : SetOperationOp<T>(ctx, DENSE_DENSE) {}
};

#define _DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(T) \
  REGISTER_KERNEL_BUILDER(Name("DenseToDenseSetOperation")       \
                              .Device(DEVICE_CPU)                \
                              .TypeConstraint<T>("T"),           \
                          DenseToDenseSetOperationOp<T>);
_DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int8);
_DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int16);
_DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int32);
_DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int64);
_DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(uint8);
_DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(uint16);
_DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(string);
#undef _DENSE_TO_DENSE_SET_OPERATION_REGISTER_KERNEL_BUILDER

template <typename T>
class DenseToSparseSetOperationOp : public SetOperationOp<T> {
 public:
  explicit DenseToSparseSetOperationOp(OpKernelConstruction* ctx)
      : SetOperationOp<T>(ctx, DENSE_SPARSE) {}
};

#define _DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(T) \
  REGISTER_KERNEL_BUILDER(Name("DenseToSparseSetOperation")       \
                              .Device(DEVICE_CPU)                 \
                              .TypeConstraint<T>("T"),            \
                          DenseToSparseSetOperationOp<T>);
_DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int8);
_DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int16);
_DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int32);
_DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int64);
_DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(uint8);
_DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(uint16);
_DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(string);
#undef _DENSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER

template <typename T>
class SparseToSparseSetOperationOp : public SetOperationOp<T> {
 public:
  explicit SparseToSparseSetOperationOp(OpKernelConstruction* ctx)
      : SetOperationOp<T>(ctx, SPARSE_SPARSE) {}
};

#define _SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(T) \
  REGISTER_KERNEL_BUILDER(Name("SparseToSparseSetOperation")       \
                              .Device(DEVICE_CPU)                  \
                              .TypeConstraint<T>("T"),             \
                          SparseToSparseSetOperationOp<T>);
_SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int8);
_SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int16);
_SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int32);
_SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(int64);
_SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(uint8);
_SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(uint16);
_SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER(string);
#undef _SPARSE_TO_SPARSE_SET_OPERATION_REGISTER_KERNEL_BUILDER

}  // namespace tensorflow


text:
<CartModifyResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
  <OperationRequest>
    <HTTPHeaders>

    </HTTPHeaders>
    <RequestId>1SHK40VXXP1SGP1H005S</RequestId>
    <Arguments>
      <Argument Name="AssociateTag" Value="XXXXXXXXXXXXXXX"/>
      <Argument Name="Service" Value="AWSECommerceService"/>
      <Argument Name="Signature" Value="XXXXXXXXXXXXXXX"/>
      <Argument Name="Item.1.Quantity" Value="1000"/>
      <Argument Name="Item.1.CartItemId" Value="0201896834"/>
      <Argument Name="HMAC" Value="uq8TI2eQLxHyWrZ53D7RaLdU8Uw="/>
      <Argument Name="Operation" Value="CartModify"/>
      <Argument Name="CartId" Value="182-5127932-5818355"/>
      <Argument Name="AWSAccessKeyId" Value="XXXXXXXXXXXXXXX"/>
      <Argument Name="Timestamp" Value="2011-11-08T21:47:37Z"/>
      <Argument Name="Version" Value="2011-08-01"/>
    </Arguments>
    <RequestProcessingTime>0.0045020580291748</RequestProcessingTime>
  </OperationRequest>
  <Cart>
    <Request>
      <IsValid>False</IsValid>
      <CartModifyRequest>
        <CartId>182-5127932-5818355</CartId>
        <HMAC>uq8TI2eQLxHyWrZ53D7RaLdU8Uw=</HMAC>
        <Items>
          <Item>
            <CartItemId>0201896834</CartItemId>
            <Quantity>1000</Quantity>
          </Item>
        </Items>
      </CartModifyRequest>
      <Errors>
        <Error>
          AWS.ParameterOutOfRange
          <Message>The value you specified for Quantity is invalid.  Valid values must be between 0 and 999.</Message>
        </Error>
      </Errors>
    </Request>
  </Cart>
</CartModifyResponse>

redpajama_set_name: RedPajamaGithub


text:
Content Management System

Upload Image


text:
Make a [pull request](https://help.github.com/articles/about-pull-requests/) (hereafter PR).
In the PR body, feel free to add an area label if appropriate by saying `/area <AREA>`.
The list of labels is [here](https://github.com/kubernetes/test-infra/labels).
Also feel free to suggest a reviewer with `/assign @theirname`.

Once your reviewer is happy, they will say `/lgtm` which will apply the
`lgtm` label, and will apply the `approved` label if they are an
[owner](/OWNERS).
The `approved` label will also automatically be applied to PRs opened by an
OWNER. If neither you nor your reviewer is an owner, please `/assign` someone
 who is.
Your PR will be automatically merged once it has the the `lgtm` and `approved`
labels, does not have any `do-not-merge/*` labels, and all tests are passing.


text:
from datetime import datetime
from oslo_config import cfg

from vitrage.common.constants import DatasourceOpts as DSOpts
from vitrage.common.constants import DatasourceProperties as DSProps
from vitrage.common.constants import EventProperties as EventProps
from vitrage.common.constants import UpdateMethod
from vitrage.datasources.doctor import DOCTOR_DATASOURCE
from vitrage.datasources.doctor.properties import DoctorDetails
from vitrage.datasources.doctor.properties import DoctorProperties \
    as DoctorProps
from vitrage.datasources.doctor.properties import DoctorStatus
from vitrage.datasources.doctor.transformer import DoctorTransformer
from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
from vitrage.datasources.nova.host.transformer import HostTransformer
from vitrage.datasources.transformer_base import TransformerBase
from vitrage.tests.mocks import mock_transformer
from vitrage.tests.unit.datasources.test_alarm_transformer_base import \
    BaseAlarmTransformerTest

# noinspection PyProtectedMember
class DoctorTransformerTest(BaseAlarmTransformerTest):

    OPTS = [
        cfg.StrOpt(DSOpts.UPDATE_METHOD,
                   default=UpdateMethod.PUSH),
    ]

    def setUp(self):
        super(DoctorTransformerTest, self).setUp()
        self.conf_reregister_opts(self.OPTS, group=DOCTOR_DATASOURCE)
        self.transformers = {}
        self.transformers[DOCTOR_DATASOURCE] = \
            DoctorTransformer(self.transformers)
        self.transformers[NOVA_HOST_DATASOURCE] = \
            HostTransformer(self.transformers)

    def test_create_update_entity_vertex(self):
        # Test setup
        time1 = datetime.now().isoformat()
        host1 = 'host1'
        event = self._generate_event(time1, host1, DoctorStatus.DOWN)
        self.assertIsNotNone(event)

        # Test action
        transformer = self.transformers[DOCTOR_DATASOURCE]
        wrapper = transformer.transform(event)

        # Test assertions
        self._validate_vertex_props(wrapper.vertex, event)
        entity_key1 = transformer._create_entity_key(event)
        entity_uuid1 = transformer.uuid_from_deprecated_vitrage_id(entity_key1)
        # Validate the neighbors: only one valid host neighbor
        self._validate_host_neighbor(wrapper, entity_uuid1, host1)

        # Validate the expected action on the graph - update or delete
        self._validate_graph_action(wrapper)

        # Create an event with status 'UP'
        time2 = datetime.now().isoformat()
        host2 = 'host2'
        event = self._generate_event(time2, host2, DoctorStatus.UP)
        self.assertIsNotNone(event)

        # Test action
        # after transform vitrage uuid will be deleted from uuid cache
        entity_key2 = transformer._create_entity_key(event)
        entity_uuid2 = \
            TransformerBase.uuid_from_deprecated_vitrage_id(entity_key2)

        transformer = self.transformers[DOCTOR_DATASOURCE]
        wrapper = transformer.transform(event)

        # Test assertions
        self._validate_vertex_props(wrapper.vertex, event)
        self._validate_host_neighbor(wrapper, entity_uuid2, host2)
        self._validate_graph_action(wrapper)

    def _validate_vertex_props(self, vertex, event):
        self._validate_alarm_vertex_props(vertex,
                                          event[EventProps.TYPE],
                                          DOCTOR_DATASOURCE,
                                          event[DSProps.SAMPLE_DATE])

    @staticmethod
    def _generate_event(time, hostname, status):
        details = {}
        if hostname:
            details[DoctorDetails.HOSTNAME] = hostname
        if status:
            details[DoctorDetails.STATUS] = status

        update_vals = {EventProps.DETAILS: details}
        if time:
            update_vals[EventProps.TIME] = time
            update_vals[DoctorProps.UPDATE_TIME] = time

        generators = mock_transformer.simple_doctor_alarm_generators(
            update_vals=update_vals)

        return mock_transformer.generate_random_events_list(generators)[0]

    def _is_erroneous(self, vertex):
        return vertex[DoctorDetails.STATUS] == DoctorStatus.DOWN


text:
class ApplicationMailer < ActionMailer::Base
  default from: 'Les Pitonneux <contact@pitonneux.com>'
  layout 'mailer'
end


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CppMathWrapper;
using std;

namespace CsharpSample
{
    class Program
    {
        static void Main(string[] args)
        {
            ManagedCppMathWrapper managedCppMathWrapper = new ManagedCppMathWrapper();

            var values = new List<Tuple<double, uint>>();
            values.Add(new Tuple<double, uint>(100.1, 1000));
            values.Add(new Tuple<double, uint>(99.98, 1350));
            values.Add(new Tuple<double, uint>(104.25, 790));

            double vwap = managedCppMathWrapper.Vwap(values);

            Console.WriteLine("vwap=" + vwap);

            Console.ReadLine();
        }
    }
}


text:
import deepFreeze from 'deep-freeze';

import unreadStreamsReducers from '../unreadStreamsReducers';
import {
  REALM_INIT,
  ACCOUNT_SWITCH,
  EVENT_NEW_MESSAGE,
  MARK_MESSAGES_READ,
  EVENT_UPDATE_MESSAGE_FLAGS,
} from '../../actionConstants';

describe('unreadStreamsReducers', () => {
  describe('ACCOUNT_SWITCH', () => {
    test('resets state to initial state', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3],
        },
      ]);

      const action = deepFreeze({
        type: ACCOUNT_SWITCH,
      });

      const expectedState = [];

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toEqual(expectedState);
    });
  });

  describe('REALM_INIT', () => {
    test('received data from "unread_msgs.streams" key replaces the current state ', () => {
      const initialState = deepFreeze([]);

      const action = deepFreeze({
        type: REALM_INIT,
        data: {
          unread_msgs: {
            streams: [
              {
                stream_id: 1,
                topic: 'some topic',
                unread_message_ids: [1, 2],
              },
            ],
            huddles: [{}, {}, {}],
            pms: [{}, {}, {}],
            mentions: [1, 2, 3],
          },
        },
      });

      const expectedState = [
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2],
        },
      ];

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toEqual(expectedState);
    });
  });

  describe('EVENT_NEW_MESSAGE', () => {
    test('if message id already exists, do not mutate state', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2],
        },
      ]);

      const action = deepFreeze({
        type: EVENT_NEW_MESSAGE,
        message: {
          id: 1,
          type: 'stream',
          stream_id: 1,
          subject: 'some topic',
        },
      });

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toBe(initialState);
    });

    test('if message is not stream, return original state', () => {
      const initialState = deepFreeze([
        {
          sender_id: 1,
          unread_message_ids: [1, 2, 3],
        },
      ]);

      const action = deepFreeze({
        type: EVENT_NEW_MESSAGE,
        message: {
          id: 4,
          type: 'private',
          sender_id: 1,
        },
      });

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toBe(initialState);
    });

    test('if message is sent by self, do not mutate state', () => {
      const initialState = deepFreeze([]);

      const action = deepFreeze({
        type: EVENT_NEW_MESSAGE,
        message: {
          id: 1,
          type: 'stream',
          stream_id: 2,
          subject: 'another topic',
          sender_email: 'me@example.com',
        },
        ownEmail: 'me@example.com',
      });

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toBe(initialState);
    });

    test('if message id does not exist, append to state', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3],
        },
      ]);

      const action = deepFreeze({
        type: EVENT_NEW_MESSAGE,
        message: {
          id: 4,
          type: 'stream',
          stream_id: 1,
          subject: 'some topic',
        },
      });

      const expectedState = [
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3, 4],
        },
      ];

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toEqual(expectedState);
    });

    test('if stream with topic does not exist, append to state', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3],
        },
      ]);

      const action = deepFreeze({
        type: EVENT_NEW_MESSAGE,
        message: {
          id: 4,
          type: 'stream',
          stream_id: 2,
          subject: 'another topic',
        },
      });

      const expectedState = [
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3],
        },
        {
          stream_id: 2,
          topic: 'another topic',
          unread_message_ids: [4],
        },
      ];

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toEqual(expectedState);
    });
  });

  describe('MARK_MESSAGES_READ', () => {
    test('when ids are not contained already, do not change the state', () => {
      const initialState = deepFreeze([]);

      const action = deepFreeze({
        type: MARK_MESSAGES_READ,
        messageIds: [1, 2, 3],
      });

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toBe(initialState);
    });

    test('if message ids exist in state, remove them', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3, 4, 5],
        },
        {
          stream_id: 2,
          topic: 'another topic',
          unread_message_ids: [6, 7],
        },
      ]);

      const action = deepFreeze({
        type: MARK_MESSAGES_READ,
        messageIds: [1, 2, 3, 6, 7],
      });

      const expectedState = [
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [4, 5],
        },
      ];

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toEqual(expectedState);
    });
  });

  describe('EVENT_UPDATE_MESSAGE_FLAGS', () => {
    test('when operation is "add" but flag is not "read" do not mutate state', () => {
      const initialState = deepFreeze([]);

      const action = {
        type: EVENT_UPDATE_MESSAGE_FLAGS,
        messages: [1, 2, 3],
        flag: 'star',
        operation: 'add',
      };

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toBe(initialState);
    });

    test('if id does not exist do not mutate state', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3, 4, 5],
        },
        {
          stream_id: 2,
          topic: 'another topic',
          unread_message_ids: [4, 5],
        },
      ]);

      const action = deepFreeze({
        type: EVENT_UPDATE_MESSAGE_FLAGS,
        messages: [6, 7],
        flag: 'read',
        operation: 'add',
      });

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toBe(initialState);
    });

    test('if ids are in state remove them', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3],
        },
        {
          stream_id: 2,
          topic: 'another topic',
          unread_message_ids: [4, 5],
        },
      ]);

      const action = deepFreeze({
        type: EVENT_UPDATE_MESSAGE_FLAGS,
        messages: [3, 4, 5, 6],
        flag: 'read',
        operation: 'add',
      });

      const expectedState = [
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2],
        },
      ];

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toEqual(expectedState);
    });

    test('when operation is "remove" do nothing', () => {
      const initialState = deepFreeze([
        {
          stream_id: 1,
          topic: 'some topic',
          unread_message_ids: [1, 2, 3, 4, 5],
        },
      ]);

      const action = deepFreeze({
        type: EVENT_UPDATE_MESSAGE_FLAGS,
        messages: [1, 2],
        flag: 'read',
        operation: 'remove',
      });

      const actualState = unreadStreamsReducers(initialState, action);

      expect(actualState).toBe(initialState);
    });
  });
});


text:
namespace v8 {
namespace internal {

ScopeIterator::ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector,
                             ScopeIterator::Option option)
    : isolate_(isolate),
      frame_inspector_(frame_inspector),
      function_(frame_inspector_->GetFunction()),
      script_(frame_inspector_->GetScript()) {
  if (!frame_inspector->GetContext()->IsContext()) {
    // Optimized frame, context or function cannot be materialized. Give up.
    return;
  }
  context_ = Handle<Context>::cast(frame_inspector->GetContext());

  // We should not instantiate a ScopeIterator for wasm frames.
  DCHECK_NE(Script::TYPE_WASM, frame_inspector->GetScript()->type());

  TryParseAndRetrieveScopes(option);
}

ScopeIterator::~ScopeIterator() { delete info_; }

Handle<Object> ScopeIterator::GetFunctionDebugName() const {
  if (!function_.is_null()) return JSFunction::GetDebugName(function_);

  if (!context_->IsNativeContext()) {
    DisallowHeapAllocation no_gc;
    ScopeInfo closure_info = context_->closure_context()->scope_info();
    Handle<String> debug_name(closure_info->FunctionDebugName(), isolate_);
    if (debug_name->length() > 0) return debug_name;
  }
  return isolate_->factory()->undefined_value();
}

ScopeIterator::ScopeIterator(Isolate* isolate, Handle<JSFunction> function)
    : isolate_(isolate), context_(function->context(), isolate) {
  if (!function->shared()->IsSubjectToDebugging()) {
    context_ = Handle<Context>();
    return;
  }
  script_ = handle(Script::cast(function->shared()->script()), isolate);
  UnwrapEvaluationContext();
}

ScopeIterator::ScopeIterator(Isolate* isolate,
                             Handle<JSGeneratorObject> generator)
    : isolate_(isolate),
      generator_(generator),
      function_(generator->function(), isolate),
      context_(generator->context(), isolate),
      script_(Script::cast(function_->shared()->script()), isolate) {
  CHECK(function_->shared()->IsSubjectToDebugging());
  TryParseAndRetrieveScopes(DEFAULT);
}

void ScopeIterator::Restart() {
  DCHECK_NOT_NULL(frame_inspector_);
  function_ = frame_inspector_->GetFunction();
  context_ = Handle<Context>::cast(frame_inspector_->GetContext());
  current_scope_ = start_scope_;
  DCHECK_NOT_NULL(current_scope_);
  UnwrapEvaluationContext();
}

void ScopeIterator::TryParseAndRetrieveScopes(ScopeIterator::Option option) {
  // Catch the case when the debugger stops in an internal function.
  Handle<SharedFunctionInfo> shared_info(function_->shared(), isolate_);
  Handle<ScopeInfo> scope_info(shared_info->scope_info(), isolate_);
  if (shared_info->script()->IsUndefined(isolate_)) {
    current_scope_ = closure_scope_ = nullptr;
    context_ = handle(function_->context(), isolate_);
    function_ = Handle<JSFunction>();
    return;
  }

  // Class fields initializer functions don't have any scope
  // information. We short circuit the parsing of the class literal
  // and return an empty context here.
  if (IsClassMembersInitializerFunction(shared_info->kind())) {
    current_scope_ = closure_scope_ = nullptr;
    context_ = Handle<Context>();
    function_ = Handle<JSFunction>();
    return;
  }

  DCHECK_NE(IGNORE_NESTED_SCOPES, option);
  bool ignore_nested_scopes = false;
  if (shared_info->HasBreakInfo() && frame_inspector_ != nullptr) {
    // The source position at return is always the end of the function,
    // which is not consistent with the current scope chain. Therefore all
    // nested with, catch and block contexts are skipped, and we can only
    // inspect the function scope.
    // This can only happen if we set a break point inside right before the
    // return, which requires a debug info to be available.
    Handle<DebugInfo> debug_info(shared_info->GetDebugInfo(), isolate_);

    // Find the break point where execution has stopped.
    BreakLocation location = BreakLocation::FromFrame(debug_info, GetFrame());

    ignore_nested_scopes = location.IsReturn();
  }

  // Reparse the code and analyze the scopes.
  // Check whether we are in global, eval or function code.
  if (scope_info->scope_type() == FUNCTION_SCOPE) {
    // Inner function.
    info_ = new ParseInfo(isolate_, shared_info);
  } else {
    // Global or eval code.
    Handle<Script> script(Script::cast(shared_info->script()), isolate_);
    info_ = new ParseInfo(isolate_, script);
    if (scope_info->scope_type() == EVAL_SCOPE) {
      info_->set_eval();
      if (!context_->IsNativeContext()) {
        info_->set_outer_scope_info(handle(context_->scope_info(), isolate_));
      }
      // Language mode may be inherited from the eval caller.
      // Retrieve it from shared function info.
      info_->set_language_mode(shared_info->language_mode());
    } else if (scope_info->scope_type() == MODULE_SCOPE) {
      DCHECK(info_->is_module());
    } else {
      DCHECK_EQ(SCRIPT_SCOPE, scope_info->scope_type());
    }
  }

  if (parsing::ParseAny(info_, shared_info, isolate_) &&
      Rewriter::Rewrite(info_)) {
    info_->ast_value_factory()->Internalize(isolate_);
    closure_scope_ = info_->literal()->scope();

    if (option == COLLECT_NON_LOCALS) {
      DCHECK(non_locals_.is_null());
      non_locals_ = info_->literal()->scope()->CollectNonLocals(
          isolate_, info_, StringSet::New(isolate_));
      if (!closure_scope_->has_this_declaration() &&
          closure_scope_->HasThisReference()) {
        non_locals_ = StringSet::Add(isolate_, non_locals_,
                                     isolate_->factory()->this_string());
      }
    }

    CHECK(DeclarationScope::Analyze(info_));
    if (ignore_nested_scopes) {
      current_scope_ = closure_scope_;
      start_scope_ = current_scope_;
      if (closure_scope_->NeedsContext()) {
        context_ = handle(context_->closure_context(), isolate_);
      }
    } else {
      RetrieveScopeChain(closure_scope_);
    }
    UnwrapEvaluationContext();
  } else {
    // A failed reparse indicates that the preparser has diverged from the
    // parser or that the preparse data given to the initial parse has been
    // faulty. We fail in debug mode but in release mode we only provide the
    // information we get from the context chain but nothing about
    // completely stack allocated scopes or stack allocated locals.
    // Or it could be due to stack overflow.
    // Silently fail by presenting an empty context chain.
    CHECK(isolate_->has_pending_exception());
    isolate_->clear_pending_exception();
    context_ = Handle<Context>();
  }
}

void ScopeIterator::UnwrapEvaluationContext() {
  if (!context_->IsDebugEvaluateContext()) return;
  Context current = *context_;
  do {
    Object wrapped = current->get(Context::WRAPPED_CONTEXT_INDEX);
    if (wrapped->IsContext()) {
      current = Context::cast(wrapped);
    } else {
      DCHECK(!current->previous().is_null());
      current = current->previous();
    }
  } while (current->IsDebugEvaluateContext());
  context_ = handle(current, isolate_);
}

Handle<JSObject> ScopeIterator::MaterializeScopeDetails() {
  // Calculate the size of the result.
  Handle<FixedArray> details =
      isolate_->factory()->NewFixedArray(kScopeDetailsSize);
  // Fill in scope details.
  details->set(kScopeDetailsTypeIndex, Smi::FromInt(Type()));
  Handle<JSObject> scope_object = ScopeObject(Mode::ALL);
  details->set(kScopeDetailsObjectIndex, *scope_object);
  if (Type() == ScopeTypeGlobal || Type() == ScopeTypeScript) {
    return isolate_->factory()->NewJSArrayWithElements(details);
  } else if (HasContext()) {
    Handle<Object> closure_name = GetFunctionDebugName();
    details->set(kScopeDetailsNameIndex, *closure_name);
    details->set(kScopeDetailsStartPositionIndex,
                 Smi::FromInt(start_position()));
    details->set(kScopeDetailsEndPositionIndex, Smi::FromInt(end_position()));
    if (InInnerScope()) {
      details->set(kScopeDetailsFunctionIndex, *function_);
    }
  }
  return isolate_->factory()->NewJSArrayWithElements(details);
}

bool ScopeIterator::HasPositionInfo() {
  return InInnerScope() || !context_->IsNativeContext();
}

int ScopeIterator::start_position() {
  if (InInnerScope()) return current_scope_->start_position();
  if (context_->IsNativeContext()) return 0;
  return context_->closure_context()->scope_info()->StartPosition();
}

int ScopeIterator::end_position() {
  if (InInnerScope()) return current_scope_->end_position();
  if (context_->IsNativeContext()) return 0;
  return context_->closure_context()->scope_info()->EndPosition();
}

bool ScopeIterator::DeclaresLocals(Mode mode) const {
  ScopeType type = Type();

  if (type == ScopeTypeWith) return mode == Mode::ALL;
  if (type == ScopeTypeGlobal) return mode == Mode::ALL;

  bool declares_local = false;
  auto visitor = [&](Handle<String> name, Handle<Object> value) {
    declares_local = true;
    return true;
  };
  VisitScope(visitor, mode);
  return declares_local;
}

bool ScopeIterator::HasContext() const {
  return !InInnerScope() || current_scope_->NeedsContext();
}

void ScopeIterator::Next() {
  DCHECK(!Done());

  ScopeType scope_type = Type();

  if (scope_type == ScopeTypeGlobal) {
    // The global scope is always the last in the chain.
    DCHECK(context_->IsNativeContext());
    context_ = Handle<Context>();
    DCHECK(Done());
    return;
  }

  bool inner = InInnerScope();
  if (current_scope_ == closure_scope_) function_ = Handle<JSFunction>();

  if (scope_type == ScopeTypeScript) {
    DCHECK_IMPLIES(InInnerScope(), current_scope_->is_script_scope());
    seen_script_scope_ = true;
    if (context_->IsScriptContext()) {
      context_ = handle(context_->previous(), isolate_);
    }
  } else if (!inner) {
    DCHECK(!context_->IsNativeContext());
    context_ = handle(context_->previous(), isolate_);
  } else {
    DCHECK_NOT_NULL(current_scope_);
    do {
      if (current_scope_->NeedsContext()) {
        DCHECK(!context_->previous().is_null());
        context_ = handle(context_->previous(), isolate_);
      }
      DCHECK_IMPLIES(InInnerScope(), current_scope_->outer_scope() != nullptr);
      current_scope_ = current_scope_->outer_scope();
      // Repeat to skip hidden scopes.
    } while (current_scope_->is_hidden());
  }

  UnwrapEvaluationContext();
}

// Return the type of the current scope.
ScopeIterator::ScopeType ScopeIterator::Type() const {
  DCHECK(!Done());
  if (InInnerScope()) {
    switch (current_scope_->scope_type()) {
      case FUNCTION_SCOPE:
        DCHECK_IMPLIES(current_scope_->NeedsContext(),
                       context_->IsFunctionContext() ||
                           context_->IsDebugEvaluateContext());
        return ScopeTypeLocal;
      case MODULE_SCOPE:
        DCHECK_IMPLIES(current_scope_->NeedsContext(),
                       context_->IsModuleContext());
        return ScopeTypeModule;
      case SCRIPT_SCOPE:
        DCHECK_IMPLIES(
            current_scope_->NeedsContext(),
            context_->IsScriptContext() || context_->IsNativeContext());
        return ScopeTypeScript;
      case WITH_SCOPE:
        DCHECK_IMPLIES(current_scope_->NeedsContext(),
                       context_->IsWithContext());
        return ScopeTypeWith;
      case CATCH_SCOPE:
        DCHECK(context_->IsCatchContext());
        return ScopeTypeCatch;
      case BLOCK_SCOPE:
        DCHECK_IMPLIES(current_scope_->NeedsContext(),
                       context_->IsBlockContext());
        return ScopeTypeBlock;
      case EVAL_SCOPE:
        DCHECK_IMPLIES(current_scope_->NeedsContext(),
                       context_->IsEvalContext());
        return ScopeTypeEval;
    }
    UNREACHABLE();
  }
  if (context_->IsNativeContext()) {
    DCHECK(context_->global_object()->IsJSGlobalObject());
    // If we are at the native context and have not yet seen script scope,
    // fake it.
    return seen_script_scope_ ? ScopeTypeGlobal : ScopeTypeScript;
  }
  if (context_->IsFunctionContext() || context_->IsEvalContext() ||
      context_->IsDebugEvaluateContext()) {
    return ScopeTypeClosure;
  }
  if (context_->IsCatchContext()) {
    return ScopeTypeCatch;
  }
  if (context_->IsBlockContext()) {
    return ScopeTypeBlock;
  }
  if (context_->IsModuleContext()) {
    return ScopeTypeModule;
  }
  if (context_->IsScriptContext()) {
    return ScopeTypeScript;
  }
  DCHECK(context_->IsWithContext());
  return ScopeTypeWith;
}

Handle<JSObject> ScopeIterator::ScopeObject(Mode mode) {
  DCHECK(!Done());

  ScopeType type = Type();
  if (type == ScopeTypeGlobal) {
    DCHECK_EQ(Mode::ALL, mode);
    return handle(context_->global_proxy(), isolate_);
  }
  if (type == ScopeTypeWith) {
    DCHECK_EQ(Mode::ALL, mode);
    return WithContextExtension();
  }

  Handle<JSObject> scope = isolate_->factory()->NewJSObjectWithNullProto();
  auto visitor = [=](Handle<String> name, Handle<Object> value) {
    JSObject::AddProperty(isolate_, scope, name, value, NONE);
    return false;
  };

  VisitScope(visitor, mode);
  return scope;
}

void ScopeIterator::VisitScope(const Visitor& visitor, Mode mode) const {
  switch (Type()) {
    case ScopeTypeLocal:
    case ScopeTypeClosure:
    case ScopeTypeCatch:
    case ScopeTypeBlock:
    case ScopeTypeEval:
      return VisitLocalScope(visitor, mode);
    case ScopeTypeModule:
      if (InInnerScope()) {
        return VisitLocalScope(visitor, mode);
      }
      DCHECK_EQ(Mode::ALL, mode);
      return VisitModuleScope(visitor);
    case ScopeTypeScript:
      DCHECK_EQ(Mode::ALL, mode);
      return VisitScriptScope(visitor);
    case ScopeTypeWith:
    case ScopeTypeGlobal:
      UNREACHABLE();
  }
}

bool ScopeIterator::SetVariableValue(Handle<String> name,
                                     Handle<Object> value) {
  DCHECK(!Done());
  name = isolate_->factory()->InternalizeString(name);
  switch (Type()) {
    case ScopeTypeGlobal:
    case ScopeTypeWith:
      break;

    case ScopeTypeEval:
    case ScopeTypeBlock:
    case ScopeTypeCatch:
    case ScopeTypeModule:
      if (InInnerScope()) return SetLocalVariableValue(name, value);
      if (Type() == ScopeTypeModule && SetModuleVariableValue(name, value)) {
        return true;
      }
      return SetContextVariableValue(name, value);

    case ScopeTypeLocal:
    case ScopeTypeClosure:
      if (InInnerScope()) {
        DCHECK_EQ(ScopeTypeLocal, Type());
        if (SetLocalVariableValue(name, value)) return true;
        // There may not be an associated context since we're InInnerScope().
        if (!current_scope_->NeedsContext()) return false;
      } else {
        DCHECK_EQ(ScopeTypeClosure, Type());
        if (SetContextVariableValue(name, value)) return true;
      }
      // The above functions only set variables statically declared in the
      // function. There may be eval-introduced variables. Check them in
      // SetContextExtensionValue.
      return SetContextExtensionValue(name, value);

    case ScopeTypeScript:
      return SetScriptVariableValue(name, value);
  }
  return false;
}

Handle<StringSet> ScopeIterator::GetNonLocals() { return non_locals_; }

#ifdef DEBUG
// Debug print of the content of the current scope.
void ScopeIterator::DebugPrint() {
  StdoutStream os;
  DCHECK(!Done());
  switch (Type()) {
    case ScopeIterator::ScopeTypeGlobal:
      os << "Global:\n";
      context_->Print(os);
      break;

    case ScopeIterator::ScopeTypeLocal: {
      os << "Local:\n";
      if (current_scope_->NeedsContext()) {
        context_->Print(os);
        if (context_->has_extension()) {
          Handle<HeapObject> extension(context_->extension(), isolate_);
          DCHECK(extension->IsJSContextExtensionObject());
          extension->Print(os);
        }
      }
      break;
    }

    case ScopeIterator::ScopeTypeWith:
      os << "With:\n";
      context_->extension()->Print(os);
      break;

    case ScopeIterator::ScopeTypeCatch:
      os << "Catch:\n";
      context_->extension()->Print(os);
      context_->get(Context::THROWN_OBJECT_INDEX)->Print(os);
      break;

    case ScopeIterator::ScopeTypeClosure:
      os << "Closure:\n";
      context_->Print(os);
      if (context_->has_extension()) {
        Handle<HeapObject> extension(context_->extension(), isolate_);
        DCHECK(extension->IsJSContextExtensionObject());
        extension->Print(os);
      }
      break;

    case ScopeIterator::ScopeTypeScript:
      os << "Script:\n";
      context_->global_object()
          ->native_context()
          ->script_context_table()
          ->Print(os);
      break;

    default:
      UNREACHABLE();
  }
  PrintF("\n");
}
#endif

int ScopeIterator::GetSourcePosition() {
  if (frame_inspector_) {
    return frame_inspector_->GetSourcePosition();
  } else {
    DCHECK(!generator_.is_null());
    SharedFunctionInfo::EnsureSourcePositionsAvailable(
        isolate_, handle(generator_->function()->shared(), isolate_));
    return generator_->source_position();
  }
}

void ScopeIterator::RetrieveScopeChain(DeclarationScope* scope) {
  DCHECK_NOT_NULL(scope);

  const int position = GetSourcePosition();

  Scope* parent = nullptr;
  Scope* current = scope;
  while (parent != current) {
    parent = current;
    for (Scope* inner_scope = current->inner_scope(); inner_scope != nullptr;
         inner_scope = inner_scope->sibling()) {
      int beg_pos = inner_scope->start_position();
      int end_pos = inner_scope->end_position();
      DCHECK((beg_pos >= 0 && end_pos >= 0) || inner_scope->is_hidden());
      if (beg_pos <= position && position < end_pos) {
        // Don't walk into inner functions.
        if (!inner_scope->is_function_scope()) {
          current = inner_scope;
        }
        break;
      }
    }
  }

  start_scope_ = current;
  current_scope_ = current;
}

void ScopeIterator::VisitScriptScope(const Visitor& visitor) const {
  Handle<JSGlobalObject> global(context_->global_object(), isolate_);
  Handle<ScriptContextTable> script_contexts(
      global->native_context()->script_context_table(), isolate_);

  // Skip the first script since that just declares 'this'.
  for (int context_index = 1; context_index < script_contexts->used();
       context_index++) {
    Handle<Context> context = ScriptContextTable::GetContext(
        isolate_, script_contexts, context_index);
    Handle<ScopeInfo> scope_info(context->scope_info(), isolate_);
    if (VisitContextLocals(visitor, scope_info, context)) return;
  }
}

void ScopeIterator::VisitModuleScope(const Visitor& visitor) const {
  DCHECK(context_->IsModuleContext());

  Handle<ScopeInfo> scope_info(context_->scope_info(), isolate_);
  if (VisitContextLocals(visitor, scope_info, context_)) return;

  int count_index = scope_info->ModuleVariableCountIndex();
  int module_variable_count = Smi::cast(scope_info->get(count_index))->value();

  Handle<Module> module(context_->module(), isolate_);

  for (int i = 0; i < module_variable_count; ++i) {
    int index;
    Handle<String> name;
    {
      String raw_name;
      scope_info->ModuleVariable(i, &raw_name, &index);
      if (ScopeInfo::VariableIsSynthetic(raw_name)) continue;
      name = handle(raw_name, isolate_);
    }
    Handle<Object> value = Module::LoadVariable(isolate_, module, index);

    // Reflect variables under TDZ as undeclared in scope object.
    if (value->IsTheHole(isolate_)) continue;
    if (visitor(name, value)) return;
  }
}

bool ScopeIterator::VisitContextLocals(const Visitor& visitor,
                                       Handle<ScopeInfo> scope_info,
                                       Handle<Context> context) const {
  // Fill all context locals to the context extension.
  for (int i = 0; i < scope_info->ContextLocalCount(); ++i) {
    Handle<String> name(scope_info->ContextLocalName(i), isolate_);
    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
    int context_index = Context::MIN_CONTEXT_SLOTS + i;
    Handle<Object> value(context->get(context_index), isolate_);
    // Reflect variables under TDZ as undefined in scope object.
    if (value->IsTheHole(isolate_)) continue;
    if (visitor(name, value)) return true;
  }
  return false;
}

bool ScopeIterator::VisitLocals(const Visitor& visitor, Mode mode) const {
  if (mode == Mode::STACK && current_scope_->is_declaration_scope() &&
      current_scope_->AsDeclarationScope()->has_this_declaration()) {
    Handle<Object> receiver = frame_inspector_ == nullptr
                                  ? handle(generator_->receiver(), isolate_)
                                  : frame_inspector_->GetReceiver();
    if (receiver->IsOptimizedOut(isolate_) || receiver->IsTheHole(isolate_)) {
      receiver = isolate_->factory()->undefined_value();
    }
    if (visitor(isolate_->factory()->this_string(), receiver)) return true;
  }

  for (Variable* var : *current_scope_->locals()) {
    DCHECK(!var->is_this());
    if (ScopeInfo::VariableIsSynthetic(*var->name())) continue;

    int index = var->index();
    Handle<Object> value;
    switch (var->location()) {
      case VariableLocation::LOOKUP:
        UNREACHABLE();
        break;

      case VariableLocation::UNALLOCATED:
        continue;

      case VariableLocation::PARAMETER: {
        if (frame_inspector_ == nullptr) {
          // Get the variable from the suspended generator.
          DCHECK(!generator_.is_null());
          FixedArray parameters_and_registers =
              generator_->parameters_and_registers();
          DCHECK_LT(index, parameters_and_registers->length());
          value = handle(parameters_and_registers->get(index), isolate_);
        } else {
          value = frame_inspector_->GetParameter(index);

          if (value->IsOptimizedOut(isolate_)) {
            value = isolate_->factory()->undefined_value();
          }
        }
        break;
      }

      case VariableLocation::LOCAL:
        if (frame_inspector_ == nullptr) {
          // Get the variable from the suspended generator.
          DCHECK(!generator_.is_null());
          FixedArray parameters_and_registers =
              generator_->parameters_and_registers();
          int parameter_count =
              function_->shared()->scope_info()->ParameterCount();
          index += parameter_count;
          DCHECK_LT(index, parameters_and_registers->length());
          value = handle(parameters_and_registers->get(index), isolate_);
          if (value->IsTheHole(isolate_)) {
            value = isolate_->factory()->undefined_value();
          }
        } else {
          value = frame_inspector_->GetExpression(index);
          if (value->IsOptimizedOut(isolate_)) {
            // We'll rematerialize this later.
            if (current_scope_->is_declaration_scope() &&
                current_scope_->AsDeclarationScope()->arguments() == var) {
              continue;
            }
            value = isolate_->factory()->undefined_value();
          } else if (value->IsTheHole(isolate_)) {
            // Reflect variables under TDZ as undeclared in scope object.
            continue;
          }
        }
        break;

      case VariableLocation::CONTEXT:
        if (mode == Mode::STACK) continue;
        DCHECK(var->IsContextSlot());
        value = handle(context_->get(index), isolate_);
        // Reflect variables under TDZ as undeclared in scope object.
        if (value->IsTheHole(isolate_)) continue;
        break;

      case VariableLocation::MODULE: {
        if (mode == Mode::STACK) continue;
        // if (var->IsExport()) continue;
        Handle<Module> module(context_->module(), isolate_);
        value = Module::LoadVariable(isolate_, module, var->index());
        // Reflect variables under TDZ as undeclared in scope object.
        if (value->IsTheHole(isolate_)) continue;
        break;
      }
    }

    if (visitor(var->name(), value)) return true;
  }
  return false;
}

// Retrieve the with-context extension object. If the extension object is
// a proxy, return an empty object.
Handle<JSObject> ScopeIterator::WithContextExtension() {
  DCHECK(context_->IsWithContext());
  if (context_->extension_receiver()->IsJSProxy()) {
    return isolate_->factory()->NewJSObjectWithNullProto();
  }
  return handle(JSObject::cast(context_->extension_receiver()), isolate_);
}

// Create a plain JSObject which materializes the block scope for the specified
// block context.
void ScopeIterator::VisitLocalScope(const Visitor& visitor, Mode mode) const {
  if (InInnerScope()) {
    if (VisitLocals(visitor, mode)) return;
    if (mode == Mode::STACK && Type() == ScopeTypeLocal) {
      // Hide |this| in arrow functions that may be embedded in other functions
      // but don't force |this| to be context-allocated. Otherwise we'd find the
      // wrong |this| value.
      if (!closure_scope_->has_this_declaration() &&
          !closure_scope_->HasThisReference()) {
        if (visitor(isolate_->factory()->this_string(),
                    isolate_->factory()->undefined_value()))
          return;
      }
      // Add |arguments| to the function scope even if it wasn't used.
      // Currently we don't yet support materializing the arguments object of
      // suspended generators. We'd need to read the arguments out from the
      // suspended generator rather than from an activation as
      // FunctionGetArguments does.
      if (frame_inspector_ != nullptr && !closure_scope_->is_arrow_scope() &&
          (closure_scope_->arguments() == nullptr ||
           frame_inspector_->GetExpression(closure_scope_->arguments()->index())
               ->IsOptimizedOut(isolate_))) {
        JavaScriptFrame* frame = GetFrame();
        Handle<JSObject> arguments = Accessors::FunctionGetArguments(
            frame, frame_inspector_->inlined_frame_index());
        if (visitor(isolate_->factory()->arguments_string(), arguments)) return;
      }
    }
  } else {
    DCHECK_EQ(Mode::ALL, mode);
    Handle<ScopeInfo> scope_info(context_->scope_info(), isolate_);
    if (VisitContextLocals(visitor, scope_info, context_)) return;
  }

  if (mode == Mode::ALL && HasContext()) {
    DCHECK(!context_->IsScriptContext());
    DCHECK(!context_->IsNativeContext());
    DCHECK(!context_->IsWithContext());
    if (!context_->scope_info()->CallsSloppyEval()) return;
    if (context_->extension_object().is_null()) return;
    Handle<JSObject> extension(context_->extension_object(), isolate_);
    Handle<FixedArray> keys =
        KeyAccumulator::GetKeys(extension, KeyCollectionMode::kOwnOnly,
                                ENUMERABLE_STRINGS)
            .ToHandleChecked();

    for (int i = 0; i < keys->length(); i++) {
      // Names of variables introduced by eval are strings.
      DCHECK(keys->get(i)->IsString());
      Handle<String> key(String::cast(keys->get(i)), isolate_);
      Handle<Object> value = JSReceiver::GetDataProperty(extension, key);
      if (visitor(key, value)) return;
    }
  }
}

bool ScopeIterator::SetLocalVariableValue(Handle<String> variable_name,
                                          Handle<Object> new_value) {
  // TODO(verwaest): Walk parameters backwards, not forwards.
  // TODO(verwaest): Use VariableMap rather than locals() list for lookup.
  for (Variable* var : *current_scope_->locals()) {
    if (String::Equals(isolate_, var->name(), variable_name)) {
      int index = var->index();
      switch (var->location()) {
        case VariableLocation::LOOKUP:
        case VariableLocation::UNALLOCATED:
          // Drop assignments to unallocated locals.
          DCHECK(var->is_this() ||
                 *variable_name == ReadOnlyRoots(isolate_).arguments_string());
          return false;

        case VariableLocation::PARAMETER: {
          if (var->is_this()) return false;
          if (frame_inspector_ == nullptr) {
            // Set the variable in the suspended generator.
            DCHECK(!generator_.is_null());
            Handle<FixedArray> parameters_and_registers(
                generator_->parameters_and_registers(), isolate_);
            DCHECK_LT(index, parameters_and_registers->length());
            parameters_and_registers->set(index, *new_value);
          } else {
            JavaScriptFrame* frame = GetFrame();
            if (frame->is_optimized()) return false;

            frame->SetParameterValue(index, *new_value);
          }
          return true;
        }

        case VariableLocation::LOCAL:
          if (frame_inspector_ == nullptr) {
            // Set the variable in the suspended generator.
            DCHECK(!generator_.is_null());
            int parameter_count =
                function_->shared()->scope_info()->ParameterCount();
            index += parameter_count;
            Handle<FixedArray> parameters_and_registers(
                generator_->parameters_and_registers(), isolate_);
            DCHECK_LT(index, parameters_and_registers->length());
            parameters_and_registers->set(index, *new_value);
          } else {
            // Set the variable on the stack.
            JavaScriptFrame* frame = GetFrame();
            if (frame->is_optimized()) return false;

            frame->SetExpression(index, *new_value);
          }
          return true;

        case VariableLocation::CONTEXT:
          DCHECK(var->IsContextSlot());
          context_->set(index, *new_value);
          return true;

        case VariableLocation::MODULE:
          if (!var->IsExport()) return false;
          Handle<Module> module(context_->module(), isolate_);
          Module::StoreVariable(module, var->index(), new_value);
          return true;
      }
      UNREACHABLE();
    }
  }

  return false;
}

bool ScopeIterator::SetContextExtensionValue(Handle<String> variable_name,
                                             Handle<Object> new_value) {
  if (!context_->has_extension()) return false;

  DCHECK(context_->extension_object()->IsJSContextExtensionObject());
  Handle<JSObject> ext(context_->extension_object(), isolate_);
  LookupIterator it(isolate_, ext, variable_name, LookupIterator::OWN);
  Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name);
  DCHECK(maybe.IsJust());
  if (!maybe.FromJust()) return false;

  CHECK(Object::SetDataProperty(&it, new_value).ToChecked());
  return true;
}

bool ScopeIterator::SetContextVariableValue(Handle<String> variable_name,
                                            Handle<Object> new_value) {
  DisallowHeapAllocation no_gc;
  VariableMode mode;
  InitializationFlag flag;
  MaybeAssignedFlag maybe_assigned_flag;
  int slot_index =
      ScopeInfo::ContextSlotIndex(context_->scope_info(), *variable_name, &mode,
                                  &flag, &maybe_assigned_flag);
  if (slot_index < 0) return false;

  context_->set(slot_index, *new_value);
  return true;
}

bool ScopeIterator::SetModuleVariableValue(Handle<String> variable_name,
                                           Handle<Object> new_value) {
  DisallowHeapAllocation no_gc;
  int cell_index;
  VariableMode mode;
  InitializationFlag init_flag;
  MaybeAssignedFlag maybe_assigned_flag;
  cell_index = context_->scope_info()->ModuleIndex(
      *variable_name, &mode, &init_flag, &maybe_assigned_flag);

  // Setting imports is currently not supported.
  if (ModuleDescriptor::GetCellIndexKind(cell_index) !=
      ModuleDescriptor::kExport) {
    return false;
  }

  Handle<Module> module(context_->module(), isolate_);
  Module::StoreVariable(module, cell_index, new_value);
  return true;
}

bool ScopeIterator::SetScriptVariableValue(Handle<String> variable_name,
                                           Handle<Object> new_value) {
  Handle<ScriptContextTable> script_contexts(
      context_->global_object()->native_context()->script_context_table(),
      isolate_);
  ScriptContextTable::LookupResult lookup_result;
  if (ScriptContextTable::Lookup(isolate_, *script_contexts, *variable_name,
                                 &lookup_result)) {
    Handle<Context> script_context = ScriptContextTable::GetContext(
        isolate_, script_contexts, lookup_result.context_index);
    script_context->set(lookup_result.slot_index, *new_value);
    return true;
  }

  return false;
}

}  // namespace internal
}  // namespace v8


text:
package com.github.ibole.infrastructure.security;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/*********************************************************************************************
 * .
 *
 *
 *
Copyright 2016, iBole Inc. All rights reserved.
 *
 *

 *

 *********************************************************************************************/

/**
 * @author bwang
 *
 */
public class ECDSACoder extends Coder {

  /**
   * 用私钥对信息生成数字签名.
   *
   * @param data 加密数据
   * @param privateKeyStr 私钥
   *
   * @return
   * @throws Exception
   */
  public static String sign(byte[] data, String privateKeyStr) throws Exception {
    // 解密由base64编码的私钥
    byte[] keyBytes = decryptBASE64(privateKeyStr);

    // 执行签名
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);

    KeyFactory keyFactory = KeyFactory.getInstance("EC");
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    Signature signature = Signature.getInstance("SHA256withECDSA");
    signature.initSign(privateKey);
    signature.update(data);

    return encryptBASE64(signature.sign());
  }

  /**
   * 校验数字签名.
   *
   * @param data 加密数据
   * @param publicKey 公钥
   * @param sign 数字签名
   *
   * @return 校验成功返回true 失败返回false
   * @throws Exception
   *
   */
  public static boolean verify(byte[] data, String publicKeyStr, String sign) throws Exception {
    // 解密由base64编码的私钥
    byte[] keyBytes = decryptBASE64(publicKeyStr);
    // 验证签名
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("EC");
    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    Signature signature = Signature.getInstance("SHA256withECDSA");
    signature.initVerify(publicKey);
    signature.update(data);
    // 验证签名是否正常
    return signature.verify(decryptBASE64(sign));
  }
}


text:
package org.apereo.portal.spring.context;

import java.util.Map;
import java.util.Properties;

/**
 * Sets system properties, ignores any properties with zero length values
 *
 * @author Eric Dalquist
 */
public final class SystemPropertySetter {
    public void setSystemProperties(Properties props) {
        for (final Map.Entry<Object, Object> propEntry : props.entrySet()) {
            final Object value = propEntry.getValue();
            if (value != null && String.valueOf(value).length() != 0) {
                System.setProperty(String.valueOf(propEntry.getKey()), String.valueOf(value));
            }
        }
    }
}


text:
namespace Unopar.GoBB.Models.Db
{
    using System;
    using System.Collections.Generic;

    public partial class Linha
    {
        public Linha()
        {
            this.LinhaRegistro = new HashSet<LinhaRegistro>();
        }

        public int ID { get; set; }
        public string Identificador { get; set; }
        public string Nome { get; set; }

        public virtual ICollection<LinhaRegistro> LinhaRegistro { get; set; }
    }
}


text:
class UrlService
  def remind_object_from_url(url)
    url
  end
end


text:
module MerchantSidekick
  class PurchaseOrder < Order
    has_many :purchase_invoices, :foreign_key => :order_id, :class_name => "MerchantSidekick::PurchaseInvoice"

    # Authorizes a payment over the order gross amount
    def authorize(payment_object, options={})
      defaults = {:order_id => number}
      options = defaults.merge(options).symbolize_keys
      transaction do
        buyer.send(:before_authorize_payment, self) if buyer && buyer.respond_to?(:before_authorize_payment)
        self.build_addresses
        self.build_invoice unless self.last_unsaved_invoice
        authorization_result = self.last_unsaved_invoice.authorize(payment_object, options)
        if authorization_result.success?
          process_payment!
        end
        buyer.send(:after_authorize_payment, self) if buyer && buyer.respond_to?(:after_authorize_payment)
        authorization_result
      end
    end

    # Captures the amount of the order that was previously authorized
    # If the capture amount
    def capture(options={})
      defaults = {:order_id => number}
      options = defaults.merge(options).symbolize_keys

      if invoice = self.purchase_invoices.find(:all, :created_at => "invoices.id ASC").last
        buyer.send(:before_capture_payment, self) if buyer && buyer.respond_to?(:before_capture_payment)
        capture_result = invoice.capture(options)
        if capture_result.success?
          approve_payment!
        end
        buyer.send(:after_capture_payment, self) if buyer && buyer.respond_to?(:after_capture_payment)
        capture_result
      end
    end

    # Pay the order and generate invoice
    def pay(payment_object, options={})
      defaults = { :order_id => number }
      options = defaults.merge(options).symbolize_keys

      # fire buyer's before_payment callback
      buyer.send(:before_payment, self) if buyer && buyer.respond_to?(:before_payment)
      self.build_addresses
      self.build_invoice unless self.last_unsaved_invoice
      payment = self.last_unsaved_invoice.purchase(payment_object, options)
      if payment.success?
        process_payment!
        approve_payment!
      end
      save!
      # fire buyer's after_payment callback
      buyer.send(:after_payment, self ) if buyer && buyer.respond_to?(:after_payment)
      payment
    end

    # Voids a previously authorized invoice payment and sets the status to cancel
    # Usage:
    #   void(options = {})
    #
    def void(options={})
      defaults = { :order_id => self[:number] }
      options = defaults.merge(options).symbolize_keys

      if invoice = self.purchase_invoices.find(:all, :created_at => "invoices.id ASC").last
        # before_payment
        buyer.send(:before_void_payment, self ) if buyer && buyer.respond_to?(:before_void_payment)
        voided_result = invoice.void(options)
        if voided_result.success?
          cancel!
        end
        save!
        # after_void_payment
        buyer.send(:after_void_payment, self) if buyer && buyer.respond_to?(:after_void_payment)
        voided_result
      end
    end

    # refunds a previously paid order
    # Note: :card_number must be supplied
    def refund(options={})
      defaults = { :order_id => number }
      options = defaults.merge(options).symbolize_keys

      if (invoice = self.purchase_invoices.find(:all, :created_at => "invoices.id ASC").last) && invoice.paid?
        # fire buyer's before_refund_payment callback
        buyer.send(:before_refund_payment, self) if buyer && buyer.respond_to?(:before_refund_payment)
        refunded_result = invoice.credit(options)
        if refunded_result.success?
          refund!
        end
        save!
        # fire buyer's after_refund_payment callback
        buyer.send(:after_refund_payment, self) if buyer && buyer.respond_to?(:after_refund_payment)
        refunded_result
      end
    end

    # E.g.
    #
    #   @order.recurring(@payment, :interval => {:length => 1, :unit => :month},
    #    :duration => {:start_date => Date.today, :occurrences => 999})
    #
    def recurring(payment_object, options={})
      defaults = {:order_id => number}
      options = defaults.merge(options).symbolize_keys

      self.build_addresses

      authorization = Payment.class_for(payment_object).recurring(
        gross_total, payment_object, payment_options(options))
      self.push_payment(authorization)
      if authorization.success?
        save(false)
        process_payment!
      else
        # we don't want to save the payment and related objects
        # when the authorization fails
        # transaction_declined!
      end
      authorization
    end

    # E.g.
    #
    #   @order.pay_recurring("c3s34", :add_line_items => @line_items)
    #
    def pay_recurring(authorization=nil, options={})
      # recurring payment
      recurring_payment = if authorization.nil?
        self.payments.recurring.find(:all, :order => "payments.id ASC").last
      elsif authorization.is_a?(Payment) && self.payments.include?(authorization)
        authorization
      else
        self.payments.find(:first, :conditions => ["payments.id = ? OR payments.reference = ? OR payments.uuid = ?", authorization])
      end

      # recurring expired
      if !self.pending? || self.purchase_invoices.paid.count > recurring_payment.duration_occurrences
        raise MerchantSidekick::RecurringPaymentError, "Recurring order #{self.number} expired"
      end

      transaction do
        buyer.send(:before_pay_recurring, self) if buyer && buyer.respond_to?(:before_pay_recurring)
        self.additional_line_items(options[:add_line_items])
        self.build_invoice unless self.last_unsaved_invoice

        authorization_result = self.last_unsaved_invoice.purchase(recurring_payment, options)
        if authorization_result.success?
          # add next billing due date
          process_payment!
        end
        buyer.send(:after_pay_recurring, self) if buyer && buyer.respond_to?(:before_pay_recurring)
        authorization_result
      end
    end

    def authorize_recurring(authorization=nil, options={})
      # recurring payment
      recurring_payment = if authorization.nil?
        self.payments.recurring.find(:all, :order => "payments.id ASC").last
      elsif authorization.is_a?(Payment) && self.payments.include?(authorization)
        authorization
      else
        self.payments.find(:first, :conditions => ["payments.id = ? OR payments.reference = ? OR payments.uuid = ?", authorization])
      end

      # recurring expired
      if !self.pending? || self.purchase_invoices.paid.count > recurring_payment.duration_occurrences
        raise MerchantSidekick::RecurringPaymentError, "Recurring order #{self.number} expired"
      end

      transaction do
        buyer.send(:before_authorize_recurring, self) if buyer && buyer.respond_to?(:before_authorize_recurring)
        self.additional_line_items(options[:add_line_items])
        self.build_invoice unless self.last_unsaved_invoice

        authorization_result = self.last_unsaved_invoice.authorize(recurring_payment, options)
        if authorization_result.success?
          process_payment!
        end
        buyer.send(:after_authorize_recurring, self) if buyer && buyer.respond_to?(:after_authorize_recurring)
        authorization_result
      end
    end

    # returns a hash of additional merchant data passed to authorize
    # you want to pass in the following additional options
    #
    #   :ip => ip address of the buyer
    #
    def payment_options(options={})
      { # general
        :buyer => self.buyer,
        :seller => self.seller,
        :payable => self,
        # active merchant relevant
        :customer => self.buyer ? "#{self.buyer.name} (#{self.buyer.id})" : nil,
        :email => self.buyer && self.buyer.respond_to?(:email) ? self.buyer.email : nil,
        :order_number => self.number,
        #:invoice => self.number,
        :merchant => self.seller ? "#{self.seller.name} (#{self.seller.id})" : nil,
        :currency => self.currency,
        :billing_address => self.billing_address ? self.billing_address.to_merchant_attributes : nil,
        :shipping_address =>  self.shipping_address ? self.shipping_address.to_merchant_attributes : nil
      }.merge(options)
    end

    # yes, i am a purchase order!
    def purchase_order?
      true
    end

    # used in build_invoice to determine which type of invoice
    def to_invoice_class_name
      "MerchantSidekick::PurchaseInvoice"
    end

    # returns last unsaved invoice
    def last_unsaved_invoice
      unless self.purchase_invoices.empty?
        self.purchase_invoices.last.new_record? ? self.purchase_invoices.last : nil
      else
        nil
      end
    end

    def build_invoice
      new_invoice = self.purchase_invoices.build(
        :line_items       => self.duplicate_line_items,
        :net_amount       => self.net_total,
        :tax_amount       => self.tax_total,
        :gross_amount     => self.gross_total,
        :buyer            => self.buyer,
        :seller           => self.seller,
        :origin_address   => self.origin_address ? self.origin_address.dup : nil,
        :billing_address  => self.billing_address ? self.billing_address.dup : nil,
        :shipping_address => self.shipping_address ? self.shipping_address.dup : nil
      )

      # set new invoice's line items to invoice we just created
      new_invoice.line_items.each do |li|
        if li.new_record?
          li.invoice = new_invoice
        else
          li.update_attribute(:invoice, new_invoice)
        end
      end

      # duplicate addresses
      new_invoice.build_origin_address(self.origin_address.content_attributes) if self.origin_address
      new_invoice.build_billing_address(self.billing_address.content_attributes) if self.billing_address
      new_invoice.build_shipping_address(self.shipping_address.content_attributes) if self.shipping_address

      new_invoice.evaluate
      @additional_line_items = nil
      new_invoice
    end

    # make sure we get a copy of the line items
    def duplicate_line_items
      result = []
      lis = self.line_items
      lis += @additional_line_items.to_a
      lis.each do |line_item|
        li = line_item.dup # Note: use clone in Rails < 3.1
        li.sellable = line_item.sellable
        li.net_amount = line_item.net_amount
        li.gross_amount = line_item.gross_amount
        li.order = nil
        result << li
      end
      result
    end

    # process additional line items before build invoice
    def additional_line_items(items)
      # add line items
      if !items.blank?
        if items.is_a?(Array) && items.all? {|i| i.is_a?(MerchantSidekick::ShoppingCart::LineItem)}
          duped = self.buyer.dup
          order = duped.purchase items
          @additional_line_items = order.line_items
        elsif items.is_a?(Array) && items.all? {|i| i.is_a?(LineItem)}
          @additional_line_items = items
        elsif items.is_a?(Array) && items.all? {|i| i.is_a?(Product)}
          # array of products
          duped = self.buyer.dup
          cart = Cart.new(self.currency)
          items.each {|product| cart.add(product)}
          order = duped.purchase cart.line_items
          @additional_line_items = order.line_items
        end
      end
    end

    # Builds billing, shipping and origin addresses
    def build_addresses(options={})
      raise ArgumentError.new("No address declared for buyer (#{buyer.class.name} ##{buyer.id}), use e.g. class #{buyer.class.name}; has_address; end") \
        unless buyer.respond_to?(:find_default_address)

      # buyer's billing or default address
      unless default_billing_address
        if buyer.respond_to?(:billing_address) && buyer.default_billing_address
          self.build_billing_address(buyer.default_billing_address.content_attributes)
        else
          if buyer_default_address = buyer.find_default_address
            self.build_billing_address(buyer_default_address.content_attributes)
          else
            raise ArgumentError.new(
              "No billing or default address for buyer (#{buyer.class.name} ##{buyer.id}), use e.g. class #{buyer.class.name}; has_address :billing; end")
          end
        end
      end

      # buyer's shipping address
      if buyer.respond_to?(:shipping_address)
        self.build_shipping_address(buyer.find_shipping_address_or_clone_from(
          self.billing_address
        ).content_attributes) unless self.default_shipping_address
      end

      self.billing_address.street = "#{Merchant::Sidekick::Version::NAME}" if self.billing_address && self.billing_address.street.to_s =~ /^backend$/
      self.shipping_address.street = "#{Merchant::Sidekick::Version::NAME}" if self.shipping_address && self.shipping_address.street.to_s =~ /^backend$/

      # seller's billing or default address
      if seller
        raise ArgumentError.new("No address for seller (#{seller.class.name} ##{seller.id}), use acts_as_addressable") \
          unless seller.respond_to?(:find_default_address)

        unless default_origin_address
          if seller.respond_to?(:billing_address) && seller.find_billing_address
            self.build_origin_address(seller.find_billing_address.content_attributes)
          else
            if seller_default_address = seller.find_default_address
              self.build_origin_address(seller_default_address.content_attributes)
            end
          end
        end
      end
    end

  end

  class ::MerchantSidekick::RecurringPaymentError < Exception
  end
end


text:
module RedisModelExtension

  module ClassCreate

    # create instance and save it
    def create args = {}
      instance = self.new(args)
      instance.save
      return instance
    end

  end

  module SaveDestroy

    # save method - save all attributes (fields) and create aliases
    def save
      perform = lambda do
        # can be saved into redis?
        if valid?

          #autoicrement id
          self.send("id=", increment_id) if redis_key_config.include?(:id) && !self.id?

          #generate key (possibly new)
          generated_key = redis_key

          #take care about renaming saved hash in redis (if key changed)
          if redis_old_keys[:key] && redis_old_keys[:key] !=  generated_key && RedisModelExtension::Database.redis {|r| r.exists(redis_old_keys[:key]) }
            RedisModelExtension::Database.redis {|r| r.rename(redis_old_keys[:key], generated_key) }
          end

          #ignore nil values for save
          args = self.class.redis_save_fields_with_nil_conf ? to_arg : to_arg.reject{|k,v| v.nil?}

          #perform save to redis hash
          RedisModelExtension::Database.redis {|r| r.hmset(generated_key, *args.inject([]){ |arr,kv| arr + [kv[0], value_to_redis(kv[0], kv[1])]}) }

          # destroy aliases
          destroy_aliases!
          create_aliases

          #after save make sure instance remember old key to know if it needs to be ranamed
          store_keys
        end
      end

      run_callbacks :save do
        unless exists?
          run_callbacks :create do
            perform.()
          end
        else
          perform.()
        end
      end
      unless errors.any?
        return self
      else
        return false
      end
    end

    # create aliases (create key value [STRING] key is alias redis key and value is redis key)
    def create_aliases
      main_key = redis_key
      redis_alias_config.each do |alias_name, fields|
        RedisModelExtension::Database.redis {|r| r.sadd(redis_alias_key(alias_name), main_key) } if valid_alias_key? alias_name
      end
    end

    # update multiple attrubutes at once
    def update args
      args.each do |key, value|
        method = "#{key}=".to_sym
        if self.respond_to? method
          self.send(method, value)
        end
      end
    end

    #remove record form database
    def destroy!
      if exists?
        run_callbacks :destroy do
          #destroy main object
          RedisModelExtension::Database.redis {|r| r.del(redis_key) }
          destroy_aliases!
        end
      end
    end

    alias :destroy :destroy!

    # remove all aliases
    def destroy_aliases!
      #do it only if it is existing object!
      if redis_old_keys[:aliases].size > 0
        redis_old_keys[:aliases].each do |alias_key|
          RedisModelExtension::Database.redis {|r| r.srem alias_key, redis_old_keys[:key] }
          #delete alias with 0 keys
          RedisModelExtension::Database.redis {|r| r.del(alias_key) } \
            if RedisModelExtension::Database.redis {|r| r.scard(alias_key) }.to_i == 0
        end
      end
    end

  end
end


text:
package com.sun.pdfview;

import com.sun.pdfview.PDFStringUtil;

import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.Charset;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.HashMap;

/**
 * A {@link CharsetEncoder} that attempts to write out the lower 8 bits
 * of any character. Characters >= 256 in value are regarded
 * as unmappable.
 *
 * @author Luke Kirby
 */
public class Identity8BitCharsetEncoder extends CharsetEncoder {

    public Identity8BitCharsetEncoder() {
        super(null, 1, 1);
    }

    protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
        while (in.remaining() > 0) {
            if (out.remaining() < 1) {
                return CoderResult.OVERFLOW;
            }
            final char c = in.get();
            if (c >= 0 && c < 256) {
                out.put((byte) c);
            } else {
                return CoderResult.unmappableForLength(1);
            }
        }
        return CoderResult.UNDERFLOW;
    }

    @Override
    public boolean isLegalReplacement(byte[] repl) {
        // avoid referencing the non-existent character set
        return true;
    }
}