বেশ কয়েকটি ফাইল জুড়ে একটি মডিউল বিভক্ত করুন


105

আমি এটিতে একাধিক স্ট্রাক্ট সহ একটি মডিউল রাখতে চাই, যার প্রতিটি তার নিজস্ব ফাইলে। Mathউদাহরণ হিসাবে একটি মডিউল ব্যবহার :

Math/
  Vector.rs
  Matrix.rs
  Complex.rs

আমি প্রতিটি স্ট্রাক্ট একই মডিউলে থাকতে চাই, যা আমি আমার মূল ফাইল থেকে ব্যবহার করব:

use Math::Vector;

fn main() {
  // ...
}

তবে মরিচা মডিউল সিস্টেম (যা শুরু করার জন্য কিছুটা বিভ্রান্তিকর) এটি করার কোনও সুস্পষ্ট উপায় সরবরাহ করে না। এটি কেবলমাত্র আপনার সম্পূর্ণ মডিউলটিকে একটি ফাইলে রাখতে দেয় বলে মনে হচ্ছে। এটা কি অ-দেহাতি? যদি না হয় তবে আমি কীভাবে এটি করব?


4
আমি ব্যাখ্যা করেছিলাম "আমি এতে একাধিক স্ট্রাক্ট সহ একটি মডিউল রাখতে চাই, প্রতিটি এটির নিজস্ব ফাইলের মধ্যে।" এর অর্থ হ'ল আপনি প্রতিটি স্ট্রাক্ট সংজ্ঞাটি নিজের ফাইলটিতে চেয়েছিলেন।
বার্টসুশি 5

4
এটি দেহাতি হিসাবে বিবেচিত হবে না, যদিও মডিউল সিস্টেম অবশ্যই এই ধরনের কাঠামোগত অনুমতি দেয়। সাধারণভাবে একটি মডিউল পথের জন্য বাঞ্ছনীয় সরাসরি একটি ফাইল সিস্টেম পাথ, যেমন struct হয় মিলা হয় foo::bar::Bazসংজ্ঞায়িত করা উচিত foo/bar.rsবা foo/bar/mod.rs
ক্রিস মরগান

উত্তর:


115

মরিচা মডিউল সিস্টেমটি আসলে অবিশ্বাস্যরূপে নমনীয় এবং ফাইলগুলিতে আপনার কোড কীভাবে কাঠামোবদ্ধ হয় তা লুকানোর সময় আপনি যে জাতীয় কাঠামো চান তা প্রকাশ করতে দেয়।

আমি মনে করি যে এখানে কীটি ব্যবহার করা pub useহবে যা আপনাকে অন্য মডিউল থেকে শনাক্তকারীদের পুনরায় রফতানি করার অনুমতি দেবে। std::ioমরিচের ক্রেটে এর নজির রয়েছে যেখানে সাব-মডিউলগুলি থেকে কিছু প্রকারের ব্যবহারের জন্য পুনরায় রফতানি করা হয়std::io

সম্পাদনা (2019-08-25): উত্তরের নিম্নলিখিত অংশটি বেশ কিছু সময় আগে লেখা হয়েছিল। এটি ব্যাখ্যা করে যে কীভাবে rustcএকা এই জাতীয় মডিউল কাঠামো সেটআপ করতে হয়। আজ, কেউ সাধারণত বেশিরভাগ ব্যবহারের ক্ষেত্রে কার্গো ব্যবহার করবে। নিম্নলিখিতটি এখনও বৈধ হলেও এর কিছু অংশ (উদাঃ #![crate_type = ...]) অদ্ভুত বলে মনে হতে পারে। এটি প্রস্তাবিত সমাধান নয়।

আপনার উদাহরণটি মানিয়ে নিতে, আমরা এই ডিরেক্টরি কাঠামো দিয়ে শুরু করতে পারি:

src/
  lib.rs
  vector.rs
main.rs

এখানে আপনার main.rs:

extern crate math;

use math::vector;

fn main() {
    println!("{:?}", vector::VectorA::new());
    println!("{:?}", vector::VectorB::new());
}

এবং আপনার src/lib.rs:

#[crate_id = "math"];
#[crate_type = "lib"];

pub mod vector; // exports the module defined in vector.rs

এবং অবশেষে src/vector.rs:

// exports identifiers from private sub-modules in the current
// module namespace
pub use self::vector_a::VectorA;
pub use self::vector_b::VectorB;

mod vector_b; // private sub-module defined in vector_b.rs

mod vector_a { // private sub-module defined in place
    #[derive(Debug)]
    pub struct VectorA {
        xs: Vec<i64>,
    }

    impl VectorA {
        pub fn new() -> VectorA {
            VectorA { xs: vec![] }
        }
    }
}

আর এখানেই যাদু ঘটে। আমরা একটি উপ-মডিউলটি সংজ্ঞায়িত করেছি math::vector::vector_aযা একটি বিশেষ ধরণের ভেক্টরের কিছু প্রয়োগ রয়েছে। তবে আমরা চাই না যে আপনার লাইব্রেরির ক্লায়েন্টরা vector_aসাব-মডিউল রয়েছে সেদিকে খেয়াল রাখুক। পরিবর্তে, আমরা এটি math::vectorমডিউলে উপলব্ধ করতে চাই । এটি করা হয়ে থাকে pub use self::vector_a::VectorA, যা vector_a::VectorAবর্তমান মডিউলে শনাক্তকারীটিকে পুনরায় রফতানি করে ।

তবে আপনি কীভাবে এটি করবেন তা জিজ্ঞাসা করেছেন যাতে আপনি আপনার বিশেষ ভেক্টর বাস্তবায়নকে বিভিন্ন ফাইলগুলিতে রাখতে পারেন। এই mod vector_b;লাইন কি করে। এটি vector_b.rsমডিউলটি বাস্তবায়নের জন্য কোনও ফাইল সন্ধানের জন্য মরিচা সংকলককে নির্দেশ দেয় । এবং যথেষ্ট নিশ্চিত, আমাদের src/vector_b.rsফাইল এখানে :

#[derive(Debug)]
pub struct VectorB {
    xs: Vec<i64>,
}

impl VectorB {
    pub fn new() -> VectorB {
        VectorB { xs: vec![] }
    }
}

ক্লায়েন্টের দৃষ্টিকোণ থেকে, সত্য যে VectorAএবংVectorB দুটি ভিন্ন ফাইলের মধ্যে দুটি ভিন্ন মডিউল সংজ্ঞায়িত করা হয় সম্পূর্ণরূপে অস্বচ্ছ হয়।

আপনি যদি একই ডিরেক্টরিতে থাকেন তবে আপনার main.rsএটি চালানো উচিত:

rustc src/lib.rs
rustc -L . main.rs
./main

সাধারণভাবে মরিচা বইয়ের "ক্রেটস এবং মডিউলস" অধ্যায়টি বেশ ভাল। এর প্রচুর উদাহরণ রয়েছে।

শেষ পর্যন্ত, মরিচা সংকলক স্বয়ংক্রিয়ভাবে আপনার জন্য উপ-ডিরেক্টরিতেও সন্ধান করে। উদাহরণস্বরূপ, উপরের কোডটি এই ডিরেক্টরি কাঠামোর সাথে অপরিবর্তিত কাজ করবে:

src/
  lib.rs
  vector/
      mod.rs
      vector_b.rs
main.rs

সংকলন এবং চালানোর আদেশগুলি একই থাকবে same


আমি বিশ্বাস করি আপনি "ভেক্টর" বলতে কী বোঝাতে চেয়েছিলেন তা আপনি ভুল বুঝেছিলেন। আমি গাণিতিক পরিমাণ হিসাবে ভেক্টরের কথা বলছিলাম , ডেটা কাঠামো নয়। এছাড়াও, আমি মরিচাটির সর্বশেষতম সংস্করণটি চালাচ্ছি না, কারণ উইন্ডোতে গড়তে এটি কিছুটা ব্যথা হয়।
তারাস্কেপ

+1 আমার যা প্রয়োজন ঠিক তা নয়, তবে আমাকে সঠিক দিকে নির্দেশ করেছেন।
স্টারস্কেপ

পছন্দ করুন এবং একটি ভেক যেমন ভেক্টর উপস্থাপন করতে ব্যবহার করা যেতে পারে। (অবশ্যই বৃহত্তর এন এর জন্য))
বার্টসুশি 5

4
@ এপিকপাইন্যাপল আপনি কী উত্তর দিতে পারেন যে আমার উত্তরটি কী মিস হয়েছে যাতে আমি এটি আপডেট করতে পারি? আমি আপনার উত্তর এবং আমার math::Vec2পরিবর্তে ব্যবহার না করে অন্যটির মধ্যে পার্থক্যটি দেখতে লড়াই করছি math::vector::Vec2। (অর্থাত, একই ধারণা কিন্তু এক মডিউল গভীর।)
BurntSushi5

4
আপনার প্রশ্নে আমি সেই মানদণ্ডটি দেখতে পাচ্ছি না। আমি যতদূর দেখতে পাচ্ছি, আমি জিজ্ঞাসা করা প্রশ্নের উত্তর দিয়েছি। (যা প্রকৃতপক্ষে ফাইলগুলি থেকে মডিউলগুলিকে কীভাবে তালাক দেবে জিজ্ঞাসা করছিল)) এটি মরিচা ০.৯-এ কাজ করছে না বলে দুঃখিত, তবে এটি অস্থির ভাষা ব্যবহারের অঞ্চল নিয়ে আসে।
বার্নসুশি 5

45

মরিচা মডিউল বিধিগুলি হ'ল:

  1. একটি উত্স ফাইল ঠিক তার নিজস্ব মডিউল (বিশেষ ফাইলগুলি মেইন.আর, লিব.আর এবং Mod.rs বাদে)।
  2. একটি ডিরেক্টরি কেবলমাত্র একটি মডিউল পাথ উপাদান।
  3. ফাইল mod.rs ঠিক হয় ডিরেক্টরির এর মডিউল।

ফাইল matrix.rs 1 ডিরেক্টরির গণিত ঠিক হয় মডিউল math::matrix। এটি সহজ. আপনি নিজের ফাইল সিস্টেমে যা দেখেন তা আপনার উত্স কোডেও খুঁজে পাবেন। এটি ফাইল পাথ এবং মডিউল পাথ 2 এর এক থেকে একের চিঠিপত্র

সুতরাং আপনি এর Matrixসাথে একটি কাঠামো আমদানি করতে পারেন use math::matrix::Matrix, কারণ স্ট্রাকটি ডিরেক্টরি গণিতে ম্যাট্রিক্স.আরএস ফাইলের ভিতরে রয়েছে। অসুখী? use math::Matrix;পরিবর্তে আপনি খুব পছন্দ করবেন, তাই না? এটা সম্ভব. math::matrix::Matrixগণিত / মোড.আর মধ্যে সনাক্তকারীটিকে পুনরায় রফতানি করুন :

pub use self::math::Matrix;

এই কাজটি পেতে আরও একটি পদক্ষেপ রয়েছে। মডিউলটি লোড করার জন্য মরিচাটির একটি মডিউল ঘোষণা দরকার । একটি যোগ করুন mod math;main.rs. মধ্যে আপনি যদি এটি না করেন তবে আপনি এই জাতীয়ভাবে আমদানি করার সময় সংকলকটির থেকে একটি ত্রুটি বার্তা পাবেন:

error: unresolved import `math::Matrix`. Maybe a missing `extern crate math`?

ইঙ্গিতটি এখানে বিভ্রান্ত করছে। অতিরিক্ত ক্রেটগুলির প্রয়োজন নেই, অবশ্যই আপনি পৃথক লাইব্রেরি লেখার ইচ্ছা নিয়ে।

এটিকে মূল.আরসের শীর্ষে যুক্ত করুন:

mod math;
pub use math::Matrix;

মডিউল ঘোষণা এছাড়াও submodules জন্য neccessary হয় vector, matrixএবং complexকারণ mathচাহিদা তাদের সেগুলিকে পুনরায় রপ্তানি করতে লোড করা হয়নি। যদি আপনি সনাক্তকারীটির মডিউলটি লোড করে থাকেন তবে কোনও শনাক্তকারীর পুনঃ-রফতানি কাজ করে। এর অর্থ হল, আপনাকে যে সনাক্তকারী math::matrix::Matrixলিখতে হবে তা পুনরায় রফতানি করতে mod matrix;। আপনি এটি গণিত / mod.rs এ করতে পারেন। সুতরাং এই বিষয়বস্তু দিয়ে ফাইলটি তৈরি করুন:

mod vector;
pub use self::vector::Vector;

mod matrix;
pub use self::matrix::Matrix;

mod complex;
pub use self::complex::Complex;

আআআন্দ তুমি হয়ে গেছ।


উত্স ফাইলের নামগুলি সাধারণত মরিচায় একটি ছোট হাতের অক্ষর দিয়ে শুরু হয়। এজন্য আমি ম্যাট্রিক্স.আরএস ব্যবহার করি না ম্যাট্রিক্স.আরএস।

2 জাভা আলাদা। আপনিও সাথে পথ ঘোষণা করেন package। এটা নিরর্থক। ফাইল সিস্টেমটিতে উত্স ফাইল অবস্থান থেকে পথটি ইতিমধ্যে স্পষ্ট। ফাইলের শীর্ষে একটি ঘোষণায় এই তথ্যগুলি কেন পুনরাবৃত্তি করবেন? অবশ্যই কখনও কখনও ফাইলের ফাইল সিস্টেমের অবস্থানটি অনুসন্ধান করার পরিবর্তে উত্স কোডটিতে তাত্ক্ষণিকভাবে নজর রাখা সহজ। আমি এমন লোকদের বুঝতে পারি যারা বলে যে এটি কম বিভ্রান্তিকর।


24

রুস্টস পিউরিস্টরা সম্ভবত আমাকে ধর্মাবলম্বী বলবেন এবং এই সমাধানটিকে ঘৃণা করবেন, তবে এটি আরও সহজ: প্রতিটি জিনিস তার নিজস্ব ফাইলে করুন, তারপরে Mod.rs " অন্তর্ভুক্ত! " ম্যাক্রো ব্যবহার করুন :

include!("math/Matrix.rs");
include!("math/Vector.rs");
include!("math/Complex.rs");

এইভাবে আপনি কোনও যুক্ত নেস্টেড মডিউল পাবেন না এবং জটিল রফতানি এবং পুনর্লিখনের নিয়মগুলি এড়ান। সহজ, কার্যকর, কোন গোলমাল।


4
আপনি সবেমাত্র নেমস্পেসিং ছুড়ে দিয়েছেন। একটি ফাইলকে অন্যের সাথে সম্পর্কিত না করে এমনভাবে পরিবর্তন করা এখন অন্যান্য ফাইলগুলি ভেঙে ফেলতে পারে। আপনার 'ব্যবহার' এর ব্যবহার অদ্ভুত হয়ে যায় (অর্থাত সবকিছুই সমান use super::*)। আপনি অন্য ফাইলগুলি থেকে কোডটি আড়াল করতে পারবেন না (যা নিরাপদ বিমূর্ত ব্যবহার নিরাপদ করার জন্য গুরুত্বপূর্ণ)
ডেমুর রুমেদ

13
হ্যাঁ, তবে সেই ক্ষেত্রে আমি ঠিক যা চেয়েছিলাম তা হ'ল: বেশ কয়েকটি ফাইল রয়েছে যা নাম স্পেসিংয়ের উদ্দেশ্যে কেবল একটি হিসাবে আচরণ করে। আমি প্রতিটি ক্ষেত্রে এটির পক্ষে কথা বলছি না, তবে যদি আপনি যে কোনও কারণেই "ফাইলের জন্য একটি মডিউল" পদ্ধতিটি ব্যবহার করতে না চান তবে এটি কার্যকর কার্যকর work
hasvn

এটি দুর্দান্ত, আমার কাছে আমার মডিউলের একটি অংশ রয়েছে যা কেবল অভ্যন্তরীণ তবে স্ব-নিরপেক্ষ এবং এটি কৌশলটি সফল হয়েছিল। আমি কাজ করার জন্য যথাযথ মডিউল সমাধান পাওয়ার চেষ্টা করব, তবে এটি এত সহজ কোথাও নেই।
rjh

7
আমি ধর্মাবলম্বী বলা যায় না, আপনার সমাধানটি সুবিধাজনক!
sailfish009

21

ঠিক আছে, কিছুক্ষণের জন্য আমার সংকলকটি যুদ্ধ করে অবশেষে এটি কাজ করে (নির্দেশ করার জন্য বার্টসুশিকে ধন্যবাদ pub use

main.rs:

use math::Vec2;
mod math;

fn main() {
  let a = Vec2{x: 10.0, y: 10.0};
  let b = Vec2{x: 20.0, y: 20.0};
}

গণিত / mod.rs:

pub use self::vector::Vec2;
mod vector;

গণিত / ভেক্টর.আরএস

use std::num::sqrt;

pub struct Vec2 {
  x: f64,
  y: f64
}

impl Vec2 {
  pub fn len(&self) -> f64 {
    sqrt(self.x * self.x + self.y * self.y) 
  }

  // other methods...
}

অন্যান্য স্ট্রাক্ট একই পদ্ধতিতে যুক্ত করা যেতে পারে। দ্রষ্টব্য: 0.9 দিয়ে সংকলিত, মাস্টার নয়।


4
লক্ষ্য করুন আপনার ব্যবহার mod math;মধ্যে main.rsদম্পতিরা আপনার mainআপনার লাইব্রেরি সঙ্গে প্রোগ্রাম। আপনি যদি চান যে আপনার mathমডিউলটি স্বাধীন হোক তবে আপনাকে এটি আলাদাভাবে সংকলন করতে হবে এবং এর সাথে লিঙ্ক করতে হবে extern crate math(আমার উত্তরে দেখানো হয়েছে)। মরিচা ০.৯-তে, এর extern mod mathপরিবর্তে বাক্য গঠনটি সম্ভব ।
বার্টসুশি 5

20
বারান্টসুশি 5 এর উত্তরটিকে সঠিক হিসাবে চিহ্নিত করা সত্যই নিখুঁত হত।
ইলুটোভ

4
@ এনএএসডিক্ট নং ফাইলগুলি থেকে মডিউলগুলিকে তালাক দিতে আপনার আলাদা ক্রেট তৈরি করার দরকার নেই। এটি ওভার ইঞ্জিনিয়ারড।
এলোমেলোভাবে

4
কেন এটি শীর্ষ ভোটের উত্তর নয় ?? প্রশ্নটি জিজ্ঞাসা করেছিল যে প্রকল্পটি কীভাবে কয়েকটি ফাইলে বিভক্ত করা যায়, যা এই উত্তরটির মতোই সহজ, এটি কীভাবে ক্রেটগুলিতে বিভক্ত করা যায় না, যা কঠোর এবং @ বার্টসুশি 5 এর উত্তর কী (সম্ভবত প্রশ্নটি সম্পাদিত হয়েছিল?)। ..
রেনাতো

6
@ বার্টসুশি 5 এর উত্তরটি গ্রহণযোগ্য উত্তর হওয়া উচিত ছিল। এটি সামাজিকভাবে বিশ্রী এবং সম্ভবত একটি প্রশ্ন জিজ্ঞাসা করা, খুব সুন্দর উত্তর পাওয়া, তারপরে এটিকে পৃথক উত্তর হিসাবে সংক্ষিপ্ত করুন এবং গ্রহণযোগ্য উত্তর হিসাবে আপনার সারাংশটি চিহ্নিত করুন।
হাসানয়াসিন 17

5

আমি এখানে যুক্ত করতে চাই যখন আপনি গভীরভাবে বাসা বেঁধে থাকেন তখন আপনি কীভাবে রস্ট ফাইলগুলি অন্তর্ভুক্ত করবেন। আমার নিম্নলিখিত কাঠামো রয়েছে:

|-----main.rs
|-----home/
|---------bathroom/
|-----------------sink.rs
|-----------------toilet.rs

আপনি কিভাবে অ্যাক্সেস sink.rsনা toilet.rsথেকে main.rs?

অন্যরা যেমন বলেছে, জাস্ট ফাইলগুলির কোনও জ্ঞান রাখে না। পরিবর্তে এটি সবকিছুকে মডিউল এবং সাবমডিউল হিসাবে দেখে। বাথরুম ডিরেক্টরিতে ফাইলগুলি অ্যাক্সেস করার জন্য আপনাকে সেগুলি রফতানি করতে হবে বা তাদের শীর্ষে ব্যারেল দেওয়া উচিত। আপনি যে ডিরেক্টরিটি অ্যাক্সেস করতে চান এবং pub mod filename_inside_the_dir_without_rs_extফাইলটির অভ্যন্তরে থাকতে চান তার কোনও ফাইলের নাম নির্দিষ্ট করে আপনি এটি করেন।

উদাহরণ।

// sink.rs
pub fn run() { 
    println!("Wash my hands for 20 secs!");
}

// toilet.rs
pub fn run() {
    println!("Ahhh... This is sooo relaxing.")
}
  1. ডিরেক্টরি bathroom.rsভিতরে বলা একটি ফাইল তৈরি করুন home:

  2. ফাইলের নাম রফতানি করুন:

    // bathroom.rs
    pub mod sink;
    pub mod toilet;
    
  3. নামক কোনো ফাইল তৈরি করুন home.rsপরবর্তীmain.rs

  4. pub mod বাথরুম.আরএস ফাইল

    // home.rs
    pub mod bathroom;
    
  5. মধ্যে main.rs

    // main.rs
    // Note: If you mod something, you just specify the 
    // topmost module, in this case, home. 
    mod home;
    
    fn main() {
        home::bathroom::sink::run();
    }
    

    use বিবৃতি ব্যবহার করা যেতে পারে:

    // main.rs
    // Note: If you mod something, you just specify the 
    // topmost module, in this case, home. 
    use home::bathroom::{sink, toilet};
    
    fn main() {
        sink::run();
        sink::toilet();
    }
    

সাব-মডিউলগুলির মধ্যে অন্যান্য ভাইবাল মডিউল (ফাইল) সহ

যদি আপনি ব্যবহার করতে চান সেটি sink.rsথেকে toilet.rs, আপনি নির্দিষ্ট করে মডিউল কল করতে পারেন selfবা superকীওয়ার্ড।

// inside toilet.rs
use self::sink;
pub fn run() {
  sink::run();
  println!("Ahhh... This is sooo relaxing.")
}

চূড়ান্ত ডিরেক্টরি কাঠামো

আপনি এরকম কিছু দিয়ে শেষ করতে চাইবেন:

|-----main.rs
|-----home.rs
|-----home/
|---------bathroom.rs
|---------bathroom/
|-----------------sink.rs
|-----------------toilet.rs

উপরের কাঠামোটি কেবল মরিচা 2018 পরে কাজ করে। নিম্নলিখিত ডিরেক্টরি কাঠামোটি 2018 এর জন্যও বৈধ, তবে 2015 কীভাবে এটি ব্যবহার করতে ব্যবহৃত হয়েছিল।

|-----main.rs
|-----home/
|---------mod.rs
|---------bathroom/
|-----------------mod.rs
|-----------------sink.rs
|-----------------toilet.rs

যার home/mod.rsমত ./home.rsএবং home/bathroom/mod.rsএকই হিসাবে একই home/bathroom.rs। মরিচটি এই পরিবর্তনটি করেছে কারণ আপনি যদি ডিরেক্টরি হিসাবে একই নামের কোনও ফাইল অন্তর্ভুক্ত করেন তবে সংকলকটি বিভ্রান্ত হবে। 2018 সংস্করণ (প্রথম দেখানো একটি) সেই কাঠামোটি ঠিক করে।

দেখুন এই রেপো আরো তথ্য এবং এই জন্য YouTube ভিডিও একটি সামগ্রিক ব্যাখ্যা জন্য।

একটি শেষ জিনিস ... হাইফেন এড়ান! snake_caseপরিবর্তে ব্যবহার করুন।

গুরুত্বপূর্ণ তথ্য

শীর্ষ ফাইলের দ্বারা গভীর ফাইলগুলির প্রয়োজনীয় না হওয়া সত্ত্বেও আপনাকে অবশ্যই সমস্ত ফাইল শীর্ষে ব্যারেল করতে হবে।

এর অর্থ, এটি sink.rsআবিষ্কার করার জন্য toilet.rs, আপনাকে সমস্ত উপায়ে উপরের পদ্ধতিগুলি ব্যবহার করে এগুলি ব্যারেল করতে হবে main.rs!

অন্য কথায়, আপনি যদি না সমস্ত উপায় অবতারণ না করেন তবে করা pub mod sink;বা use self::sink; অভ্যন্তরীণ কাজtoilet.rs করবে নাmain.rs !

অতএব, সর্বদা আপনার ফাইলগুলি শীর্ষে ব্যারেল করতে ভুলবেন না!


4
... এটি সি ++ এর সাথে তুলনায় উন্মাদভাবে সংশ্লেষিত, যা কিছু বলছে
জোসেফ গারভিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.